aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lu <chris.lu@gmail.com>2014-03-09 23:12:05 -0700
committerChris Lu <chris.lu@gmail.com>2014-03-09 23:12:05 -0700
commiteac9c4d86b7c7c9683504566e680bfb6531bfbff (patch)
tree85cebf8c26f13314d68379fd013b534c8fe8d6fa
parent86b17e8972ffafbb68fce51521ed7e053f908cef (diff)
downloadseaweedfs-eac9c4d86b7c7c9683504566e680bfb6531bfbff.tar.xz
seaweedfs-eac9c4d86b7c7c9683504566e680bfb6531bfbff.zip
better benchmarking statistics
-rw-r--r--go/weed/benchmark.go129
1 files changed, 91 insertions, 38 deletions
diff --git a/go/weed/benchmark.go b/go/weed/benchmark.go
index dfba52b06..f9a775c32 100644
--- a/go/weed/benchmark.go
+++ b/go/weed/benchmark.go
@@ -6,8 +6,8 @@ import (
"code.google.com/p/weed-fs/go/operation"
"code.google.com/p/weed-fs/go/util"
"fmt"
- "github.com/patrick-higgins/summstat"
"io"
+ "math"
"os"
"strings"
"sync"
@@ -68,13 +68,9 @@ var cmdBenchmark = &Command{
}
var (
- countWritten int64
- sizeWritten int64
- countRead int64
- sizeRead int64
- wait sync.WaitGroup
- writeStats stats
- readStats stats
+ wait sync.WaitGroup
+ writeStats *stats
+ readStats *stats
)
func runbenchmark(cmd *Command, args []string) bool {
@@ -88,39 +84,40 @@ func runbenchmark(cmd *Command, args []string) bool {
wait.Add(*b.concurrency)
go writeFileIds(*b.idListFile, fileIdLineChan, finishChan)
for i := 0; i < *b.concurrency; i++ {
- go writeFiles(idChan, fileIdLineChan)
+ go writeFiles(idChan, fileIdLineChan, writeStats)
}
+ writeStats.start = time.Now()
for i := 0; i < *b.numberOfFiles; i++ {
idChan <- i
}
close(idChan)
wait.Wait()
+ writeStats.end = time.Now()
wait.Add(1)
finishChan <- true
wait.Wait()
- println("completed", countWritten, "write requests, bytes:", sizeWritten)
- writeStats.printStats()
+ writeStats.printStats("Writing Benchmark")
}
if *b.read {
readStats = newStats()
wait.Add(*b.concurrency)
go readFileIds(*b.idListFile, fileIdLineChan)
+ readStats.start = time.Now()
for i := 0; i < *b.concurrency; i++ {
- go readFiles(fileIdLineChan)
+ go readFiles(fileIdLineChan, readStats)
}
wait.Wait()
- println("completed", countRead, "read requests, bytes:", sizeRead)
- readStats.printStats()
+ readStats.end = time.Now()
+ readStats.printStats("Randomly Reading Benchmark")
}
return true
}
-func writeFiles(idChan chan int, fileIdLineChan chan string) {
+func writeFiles(idChan chan int, fileIdLineChan chan string, s *stats) {
for {
if id, ok := <-idChan; ok {
- countWritten++
start := time.Now()
fp := &operation.FilePart{Reader: &FakeReader{id: uint64(id), size: int64(*b.fileSize)}, FileSize: int64(*b.fileSize)}
if assignResult, err := operation.Assign(*b.server, 1, ""); err == nil {
@@ -128,11 +125,13 @@ func writeFiles(idChan chan int, fileIdLineChan chan string) {
fp.Upload(0, *b.server, "")
writeStats.addSample(time.Now().Sub(start))
fileIdLineChan <- fp.Fid
- sizeWritten += int64(*b.fileSize)
+ s.transferred += int64(*b.fileSize)
+ s.completed++
if *cmdBenchmark.IsDebug {
fmt.Printf("writing %d file %s\n", id, fp.Fid)
}
} else {
+ s.failed++
println("writing file error:", err.Error())
}
} else {
@@ -142,7 +141,7 @@ func writeFiles(idChan chan int, fileIdLineChan chan string) {
wait.Done()
}
-func readFiles(fileIdLineChan chan string) {
+func readFiles(fileIdLineChan chan string, s *stats) {
for {
if fid, ok := <-fileIdLineChan; ok {
if len(fid) == 0 {
@@ -168,13 +167,15 @@ func readFiles(fileIdLineChan chan string) {
if server, ok := b.vid2server[vid]; ok {
url := "http://" + server + "/" + fid
if bytesRead, err := util.Get(url); err == nil {
- countRead++
- sizeRead += int64(len(bytesRead))
+ s.completed++
+ s.transferred += int64(len(bytesRead))
readStats.addSample(time.Now().Sub(start))
} else {
+ s.failed++
println("!!!! Failed to read from ", url, " !!!!!")
}
} else {
+ s.failed++
println("!!!! volume id ", vid, " location not found!!!!!")
}
} else {
@@ -221,31 +222,83 @@ func readFileIds(fileName string, fileIdLineChan chan string) {
close(fileIdLineChan)
}
+const (
+ benchResolution = 10000 //0.1 microsecond
+ benchBucket = 1000000000 / benchResolution
+)
+
type stats struct {
- stats *summstat.Stats
+ data []int
+ completed int
+ failed int
+ transferred int64
+ start time.Time
+ end time.Time
}
-func newStats() stats {
- s := stats{stats: summstat.NewStats()}
- s.stats.CreateBins(21, 1000, 20000)
- return s
+var percentages = []int{50, 66, 75, 80, 90, 95, 98, 99, 100}
+
+func newStats() *stats {
+ return &stats{data: make([]int, benchResolution)}
}
func (s stats) addSample(d time.Duration) {
- //fmt.Printf("adding %d μs\n", int(d / 1000))
- s.stats.AddSample(summstat.Sample(int(d / 1000)))
+ s.data[int(d/benchBucket)]++
}
-func (s stats) printStats() {
- fmt.Printf("\n%s Count:%d ", time.Now().Local(), s.stats.Count())
- fmt.Printf("Min:%.2fms ", s.stats.Min()/1000)
- fmt.Printf("Max:%.2fms ", s.stats.Max()/1000)
- fmt.Printf("Stddev:%.2fms\n", s.stats.Stddev()/1000)
- for b := 0; b < s.stats.NBins(); b++ {
- count, _, _ := s.stats.Bin(b)
- if b+1 != s.stats.NBins() {
- fmt.Printf("%2d ~ %2d ms: %2.4f%% %d\n", b, (b + 1), float64(count)*100.0/float64(s.stats.Count()), count)
- } else {
- fmt.Printf("%2d ~ ms: %2.4f%% %d\n", b, float64(count)*100.0/float64(s.stats.Count()), count)
+
+func (s stats) printStats(testName string) {
+ fmt.Printf("\n------------ %s ----------\n", testName)
+ timeTaken := float64(int64(s.end.Sub(s.start))) / 1000000000
+ fmt.Printf("Concurrency Level: %d\n", *b.concurrency)
+ fmt.Printf("Time taken for tests: %.3f seconds\n", timeTaken)
+ fmt.Printf("Complete requests: %d\n", s.completed)
+ fmt.Printf("Failed requests: %d\n", s.failed)
+ fmt.Printf("Total transferred: %d bytes\n", s.transferred)
+ fmt.Printf("Requests per second: %.2f [#/sec]\n", float64(s.completed)/timeTaken)
+ fmt.Printf("Transfer rate: %.2f [Kbytes/sec]\n", float64(s.transferred)/1024/timeTaken)
+ n, sum := 0, 0
+ min, max := 10000000, 0
+ for i := 0; i < len(s.data); i++ {
+ n += s.data[i]
+ sum += s.data[i] * i
+ if s.data[i] > 0 {
+ if min > i {
+ min = i
+ }
+ if max < i {
+ max = i
+ }
+ }
+ }
+ avg := float64(sum) / float64(n)
+ varianceSum := 0.0
+ for i := 0; i < len(s.data); i++ {
+ if s.data[i] > 0 {
+ d := float64(i) - avg
+ varianceSum += d * d * float64(s.data[i])
+ }
+ }
+ std := math.Sqrt(varianceSum / float64(n))
+ fmt.Printf("\nConnection Times (ms)\n")
+ fmt.Printf(" min avg max std\n")
+ fmt.Printf("Total: %2.1f %3.1f %3.1f %3.1f\n", float32(min)/10, float32(avg)/10, float32(max)/10, std/10)
+ //printing percentiles
+ fmt.Printf("\nPercentage of the requests served within a certain time (ms)\n")
+ percentiles := make([]int, len(percentages))
+ for i := 0; i < len(percentages); i++ {
+ percentiles[i] = n * percentages[i] / 100
+ }
+ percentiles[len(percentiles)-1] = n
+ percentileIndex := 0
+ currentSum := 0
+ for i := 0; i < len(s.data); i++ {
+ currentSum += s.data[i]
+ if s.data[i] > 0 && percentileIndex < len(percentiles) && currentSum >= percentiles[percentileIndex] {
+ fmt.Printf(" %3d%% %5.1f ms\n", percentages[percentileIndex], float32(i)/10.0)
+ percentileIndex++
+ for percentileIndex < len(percentiles) && currentSum >= percentiles[percentileIndex] {
+ percentileIndex++
+ }
}
}
}