Skip to content

Commit

Permalink
Improve the statistics for tracking read & write operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmeador authored and ncw committed Nov 21, 2015
1 parent 719f230 commit 9500133
Showing 1 changed file with 61 additions and 9 deletions.
70 changes: 61 additions & 9 deletions stressdisk.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ var (
stats *Stats
)

// enum program mode
const (
modeNone = iota
modeRead
modeReadDone
modeWrite
modeWriteDone
)

// Random contains the state for the random stream generator
type Random struct {
extendedData []byte
Expand All @@ -87,27 +96,66 @@ func NewRandom() *Random {

// Stats stores accumulated statistics
type Stats struct {
read uint64
written uint64
errors uint64
start time.Time
read uint64
written uint64
errors uint64
start time.Time
readStart time.Time // start of unaccumulated time of read operation
readSeconds float64 // read seconds accumulator
writeStart time.Time // start of unaccumulated time of write operation
writeSeconds float64 // write seconds accumulator
mode int // current mode - modeNone, modeRead, modeWrite
}

// NewStats cretates an initialised Stats
func NewStats() *Stats {
return &Stats{start: time.Now()}
}

// Be sure to transition from for example modeRead to modeRead,
// before transitioning to modeWrite, otherwise you will lose the
// corresponding time statistic in the time accumulator.
// Also you must for enter modeRead before transition to modeReadDone.
func (s *Stats) SetMode(mode int) {
s.mode = mode
switch s.mode {
default:
case modeNone:
case modeRead:
s.readStart = time.Now()
case modeReadDone:
s.readSeconds += time.Now().Sub(s.readStart).Seconds()
case modeWrite:
s.writeStart = time.Now()
case modeWriteDone:
s.writeSeconds += time.Now().Sub(s.writeStart).Seconds()
}
}

// String convert the Stats to a string for printing
func (s *Stats) String() string {
dt := time.Now().Sub(s.start)
dt_seconds := dt.Seconds()
dt := time.Now().Sub(s.start) // total elapsed time
read, written := atomic.LoadUint64(&s.read), atomic.LoadUint64(&s.written)
read_speed, write_speed := 0.0, 0.0
if dt > 0 {
read_speed = float64(read) / MB / dt_seconds
write_speed = float64(written) / MB / dt_seconds

// calculate interim duration - for periodic stats display
// while operation is not completed.
switch s.mode {
case modeRead:
s.readSeconds += time.Now().Sub(s.readStart).Seconds()
s.readStart = time.Now()
case modeWrite:
s.writeSeconds += time.Now().Sub(s.writeStart).Seconds()
s.writeStart = time.Now()
}

if s.readSeconds != 0 {
read_speed = float64(read) / MB / s.readSeconds
}
if s.writeSeconds != 0 {
write_speed = float64(written) / MB / s.writeSeconds
}

return fmt.Sprintf(`
Bytes read: %10d MByte (%7.2f MByte/s)
Bytes written: %10d MByte (%7.2f MByte/s)
Expand Down Expand Up @@ -349,6 +397,7 @@ func WriteFile(file string, size int64) bool {
random := NewRandom()
br := NewBlockReader(random, "random")
defer br.Close()
stats.SetMode(modeWrite)
for size > 0 {
block := br.Read()
_, err := out.Write(block)
Expand All @@ -361,6 +410,7 @@ func WriteFile(file string, size int64) bool {
size -= BlockSize
stats.Written(BlockSize)
}
stats.SetMode(modeWriteDone)

out.Close()
if failed {
Expand Down Expand Up @@ -391,6 +441,7 @@ func ReadTwoFiles(file1, file2 string) {

log.Printf("Reading file %q, %q\n", file1, file2)

stats.SetMode(modeRead)
pos := int64(0)
br1 := NewBlockReader(in1, file1)
defer br1.Close()
Expand All @@ -413,6 +464,7 @@ func ReadTwoFiles(file1, file2 string) {
br1.Return(block1)
br2.Return(block2)
}
stats.SetMode(modeReadDone)
}

// syntaxError prints the syntax
Expand Down

0 comments on commit 9500133

Please sign in to comment.