Merge "veyron/runtimes/google/ipc: Add Glob benchmarks"
diff --git a/runtimes/google/ipc/benchmarks/glob/README.txt b/runtimes/google/ipc/benchmarks/glob/README.txt
new file mode 100644
index 0000000..0103cd2
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/glob/README.txt
@@ -0,0 +1,120 @@
+Glob Benchmarks
+
+The benchmarks in this directory attempt to provide some guidance for the amount
+of buffering to use with the channels returned by Glob__ and GlobChildren__.
+
+The first set of benchmarks (BenchmarkChanN) shows the relationship between the
+buffer size and the latency of a very simple channel with one writer and one
+reader doing nothing else.
+
+The second set of benchmarks (BenchmarkGlobN) does the same thing but with a
+Glob__ server and a Glob client. The third set (BenchmarkGlobChildrenN) uses
+GlobChildren__.
+
+As of 2014-12-03, the conclusion is that the queue size has very little impact
+on performance.
+
+The BenchmarkChanN set shows that increasing the queue size improves latency for
+the very simple case, but not for Glob__ or GlobChildren__.
+
+An interesting observation is that all the benchmarks get slower as the number
+of cpus increases.
+
+Below are the test results for 1, 2, and 4 cpus on a HP Z420 workstation with
+2 × 6 cpu cores (Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz).
+
+$ ./glob.test -test.bench=. -test.benchtime=5s -test.cpu=1
+BenchmarkChan0 20000000 464 ns/op
+BenchmarkChan1 20000000 585 ns/op
+BenchmarkChan2 20000000 484 ns/op
+BenchmarkChan4 20000000 425 ns/op
+BenchmarkChan8 50000000 396 ns/op
+BenchmarkChan16 50000000 381 ns/op
+BenchmarkChan32 50000000 371 ns/op
+BenchmarkChan64 50000000 365 ns/op
+BenchmarkChan128 50000000 363 ns/op
+BenchmarkChan256 50000000 362 ns/op
+BenchmarkGlob0 500000 35029 ns/op
+BenchmarkGlob1 500000 63536 ns/op
+BenchmarkGlob2 500000 34753 ns/op
+BenchmarkGlob4 500000 26379 ns/op
+BenchmarkGlob8 500000 19293 ns/op
+BenchmarkGlob16 1000000 18149 ns/op
+BenchmarkGlob32 500000 52364 ns/op
+BenchmarkGlob64 500000 83879 ns/op
+BenchmarkGlob128 100000 88448 ns/op
+BenchmarkGlob256 100000 57922 ns/op
+BenchmarkGlobChildren0 100000 118448 ns/op
+BenchmarkGlobChildren1 100000 123274 ns/op
+BenchmarkGlobChildren2 100000 116110 ns/op
+BenchmarkGlobChildren4 100000 134175 ns/op
+BenchmarkGlobChildren8 100000 118776 ns/op
+BenchmarkGlobChildren16 100000 123191 ns/op
+BenchmarkGlobChildren32 100000 132195 ns/op
+BenchmarkGlobChildren64 100000 126004 ns/op
+BenchmarkGlobChildren128 100000 135072 ns/op
+BenchmarkGlobChildren256 100000 127399 ns/op
+
+$ ./glob.test -test.bench=. -test.benchtime=5s -test.cpu=2
+BenchmarkChan0-2 5000000 1595 ns/op
+BenchmarkChan1-2 5000000 1649 ns/op
+BenchmarkChan2-2 10000000 1245 ns/op
+BenchmarkChan4-2 10000000 1299 ns/op
+BenchmarkChan8-2 10000000 982 ns/op
+BenchmarkChan16-2 10000000 929 ns/op
+BenchmarkChan32-2 10000000 916 ns/op
+BenchmarkChan64-2 10000000 903 ns/op
+BenchmarkChan128-2 10000000 907 ns/op
+BenchmarkChan256-2 10000000 914 ns/op
+BenchmarkGlob0-2 500000 61455 ns/op
+BenchmarkGlob1-2 500000 46890 ns/op
+BenchmarkGlob2-2 200000 56462 ns/op
+BenchmarkGlob4-2 500000 22783 ns/op
+BenchmarkGlob8-2 200000 64783 ns/op
+BenchmarkGlob16-2 1000000 68119 ns/op
+BenchmarkGlob32-2 200000 78611 ns/op
+BenchmarkGlob64-2 500000 82180 ns/op
+BenchmarkGlob128-2 1000000 81548 ns/op
+BenchmarkGlob256-2 100000 88278 ns/op
+BenchmarkGlobChildren0-2 100000 83188 ns/op
+BenchmarkGlobChildren1-2 100000 81751 ns/op
+BenchmarkGlobChildren2-2 100000 81896 ns/op
+BenchmarkGlobChildren4-2 100000 81857 ns/op
+BenchmarkGlobChildren8-2 100000 81531 ns/op
+BenchmarkGlobChildren16-2 100000 89915 ns/op
+BenchmarkGlobChildren32-2 100000 81112 ns/op
+BenchmarkGlobChildren64-2 100000 80997 ns/op
+BenchmarkGlobChildren128-2 100000 81350 ns/op
+BenchmarkGlobChildren256-2 100000 81344 ns/op
+
+$ ./glob.test -test.bench=. -test.benchtime=5s -test.cpu=4
+BenchmarkChan0-4 5000000 2012 ns/op
+BenchmarkChan1-4 5000000 3149 ns/op
+BenchmarkChan2-4 5000000 1839 ns/op
+BenchmarkChan4-4 10000000 957 ns/op
+BenchmarkChan8-4 20000000 660 ns/op
+BenchmarkChan16-4 20000000 523 ns/op
+BenchmarkChan32-4 20000000 507 ns/op
+BenchmarkChan64-4 20000000 509 ns/op
+BenchmarkChan128-4 20000000 507 ns/op
+BenchmarkChan256-4 20000000 511 ns/op
+BenchmarkGlob0-4 100000 103269 ns/op
+BenchmarkGlob1-4 100000 101222 ns/op
+BenchmarkGlob2-4 100000 102049 ns/op
+BenchmarkGlob4-4 100000 102763 ns/op
+BenchmarkGlob8-4 100000 101939 ns/op
+BenchmarkGlob16-4 100000 102989 ns/op
+BenchmarkGlob32-4 100000 103898 ns/op
+BenchmarkGlob64-4 100000 102838 ns/op
+BenchmarkGlob128-4 100000 101532 ns/op
+BenchmarkGlob256-4 100000 101059 ns/op
+BenchmarkGlobChildren0-4 100000 106617 ns/op
+BenchmarkGlobChildren1-4 100000 102576 ns/op
+BenchmarkGlobChildren2-4 100000 106313 ns/op
+BenchmarkGlobChildren4-4 100000 102774 ns/op
+BenchmarkGlobChildren8-4 100000 102886 ns/op
+BenchmarkGlobChildren16-4 100000 106771 ns/op
+BenchmarkGlobChildren32-4 100000 103309 ns/op
+BenchmarkGlobChildren64-4 100000 105112 ns/op
+BenchmarkGlobChildren128-4 100000 102295 ns/op
+BenchmarkGlobChildren256-4 100000 102951 ns/op
diff --git a/runtimes/google/ipc/benchmarks/glob/glob_test.go b/runtimes/google/ipc/benchmarks/glob/glob_test.go
new file mode 100644
index 0000000..9168796
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/glob/glob_test.go
@@ -0,0 +1,252 @@
+package glob_test
+
+import (
+ "fmt"
+ "testing"
+
+ "veyron.io/veyron/veyron2"
+ "veyron.io/veyron/veyron2/ipc"
+ "veyron.io/veyron/veyron2/naming"
+ "veyron.io/veyron/veyron2/rt"
+ "veyron.io/veyron/veyron2/security"
+
+ "veyron.io/veyron/veyron/profiles"
+)
+
+func RunBenchmarkChan(b *testing.B, bufferSize int) {
+ ch := make(chan string, bufferSize)
+ go func() {
+ for i := 0; i < b.N; i++ {
+ ch <- fmt.Sprintf("%09d", i)
+ }
+ close(ch)
+ }()
+ for _ = range ch {
+ continue
+ }
+}
+
+func BenchmarkChan0(b *testing.B) {
+ RunBenchmarkChan(b, 0)
+}
+
+func BenchmarkChan1(b *testing.B) {
+ RunBenchmarkChan(b, 1)
+}
+
+func BenchmarkChan2(b *testing.B) {
+ RunBenchmarkChan(b, 2)
+}
+
+func BenchmarkChan4(b *testing.B) {
+ RunBenchmarkChan(b, 4)
+}
+
+func BenchmarkChan8(b *testing.B) {
+ RunBenchmarkChan(b, 8)
+}
+
+func BenchmarkChan16(b *testing.B) {
+ RunBenchmarkChan(b, 16)
+}
+
+func BenchmarkChan32(b *testing.B) {
+ RunBenchmarkChan(b, 32)
+}
+
+func BenchmarkChan64(b *testing.B) {
+ RunBenchmarkChan(b, 64)
+}
+
+func BenchmarkChan128(b *testing.B) {
+ RunBenchmarkChan(b, 128)
+}
+
+func BenchmarkChan256(b *testing.B) {
+ RunBenchmarkChan(b, 256)
+}
+
+type disp struct {
+ obj interface{}
+}
+
+func (d *disp) Lookup(suffix string) (interface{}, security.Authorizer, error) {
+ return d.obj, nil, nil
+}
+
+func startServer(b *testing.B, rt veyron2.Runtime, obj interface{}) (string, func(), error) {
+ server, err := rt.NewServer()
+ if err != nil {
+ return "", nil, fmt.Errorf("failed to start server: %v", err)
+ }
+ endpoints, err := server.Listen(profiles.LocalListenSpec)
+ if err != nil {
+ return "", nil, fmt.Errorf("failed to listen: %v", err)
+ }
+ if err := server.ServeDispatcher("", &disp{obj}); err != nil {
+ return "", nil, err
+ }
+ addr := naming.JoinAddressName(endpoints[0].String(), "")
+ return addr, func() { server.Stop() }, nil
+}
+
+type globObject struct {
+ b *testing.B
+ bufferSize int
+}
+
+func (o *globObject) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
+ if pattern != "*" {
+ panic("this benchmark only works with pattern='*'")
+ }
+ ch := make(chan naming.VDLMountEntry, o.bufferSize)
+ go func() {
+ for i := 0; i < o.b.N; i++ {
+ name := fmt.Sprintf("%09d", i)
+ ch <- naming.VDLMountEntry{Name: name}
+ }
+ close(ch)
+ }()
+ return ch, nil
+}
+
+type globChildrenObject struct {
+ b *testing.B
+ bufferSize int
+}
+
+func (o *globChildrenObject) GlobChildren__(ctx ipc.ServerContext) (<-chan string, error) {
+ if ctx.Suffix() != "" {
+ return nil, nil
+ }
+ ch := make(chan string, o.bufferSize)
+ go func() {
+ for i := 0; i < o.b.N; i++ {
+ ch <- fmt.Sprintf("%09d", i)
+ }
+ close(ch)
+ }()
+ return ch, nil
+}
+
+func globClient(b *testing.B, rt veyron2.Runtime, name string) (int, error) {
+ call, err := rt.Client().StartCall(rt.NewContext(), name, ipc.GlobMethod, []interface{}{"*"})
+ if err != nil {
+ return 0, err
+ }
+ var me naming.VDLMountEntry
+ b.ResetTimer()
+ count := 0
+ for {
+ if err := call.Recv(&me); err != nil {
+ break
+ }
+ count++
+ }
+ b.StopTimer()
+ if ferr := call.Finish(&err); ferr != nil {
+ err = ferr
+ }
+ return count, err
+}
+
+func RunBenchmarkGlob(b *testing.B, obj interface{}) {
+ runtime, err := rt.New()
+ if err != nil {
+ panic(err)
+ }
+ defer runtime.Cleanup()
+ addr, stop, err := startServer(b, runtime, obj)
+ if err != nil {
+ b.Fatalf("startServer failed: %v", err)
+ }
+ defer stop()
+
+ count, err := globClient(b, runtime, addr)
+ if err != nil {
+ b.Fatalf("globClient failed: %v", err)
+ }
+ if count != b.N {
+ b.Fatalf("unexpected number of results: got %d, expected %d", count, b.N)
+ }
+}
+
+func BenchmarkGlob0(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 0})
+}
+
+func BenchmarkGlob1(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 1})
+}
+
+func BenchmarkGlob2(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 2})
+}
+
+func BenchmarkGlob4(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 4})
+}
+
+func BenchmarkGlob8(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 8})
+}
+
+func BenchmarkGlob16(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 16})
+}
+
+func BenchmarkGlob32(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 32})
+}
+
+func BenchmarkGlob64(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 64})
+}
+
+func BenchmarkGlob128(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 128})
+}
+
+func BenchmarkGlob256(b *testing.B) {
+ RunBenchmarkGlob(b, &globObject{b, 256})
+}
+
+func BenchmarkGlobChildren0(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 0})
+}
+
+func BenchmarkGlobChildren1(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 1})
+}
+
+func BenchmarkGlobChildren2(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 2})
+}
+
+func BenchmarkGlobChildren4(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 4})
+}
+
+func BenchmarkGlobChildren8(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 8})
+}
+
+func BenchmarkGlobChildren16(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 16})
+}
+
+func BenchmarkGlobChildren32(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 32})
+}
+
+func BenchmarkGlobChildren64(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 64})
+}
+
+func BenchmarkGlobChildren128(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 128})
+}
+
+func BenchmarkGlobChildren256(b *testing.B) {
+ RunBenchmarkGlob(b, &globChildrenObject{b, 256})
+}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index e7cfc9d..149a69d 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -334,7 +334,7 @@
if n == nil {
return nil, verror.Make(errOperationFailed, context)
}
- ch := make(chan string, 100)
+ ch := make(chan string)
go func() {
for k, _ := range n.children {
ch <- k
diff --git a/services/mgmt/device/impl/app_service.go b/services/mgmt/device/impl/app_service.go
index dc61c02..b07ab26 100644
--- a/services/mgmt/device/impl/app_service.go
+++ b/services/mgmt/device/impl/app_service.go
@@ -1226,7 +1226,7 @@
if n == nil {
return nil, verror2.Make(ErrInvalidSuffix, nil)
}
- ch := make(chan string, 100)
+ ch := make(chan string)
go func() {
for child, _ := range n.children {
ch <- child
diff --git a/services/mgmt/logreader/impl/logfile.go b/services/mgmt/logreader/impl/logfile.go
index 280e5d3..a79df13 100644
--- a/services/mgmt/logreader/impl/logfile.go
+++ b/services/mgmt/logreader/impl/logfile.go
@@ -129,8 +129,7 @@
return nil, nil
}
- const batchSize = 100
- ch := make(chan string, batchSize)
+ ch := make(chan string)
go func() {
defer close(ch)
f, err := os.Open(dirName)
@@ -139,7 +138,7 @@
}
defer f.Close()
for {
- fi, err := f.Readdir(batchSize)
+ fi, err := f.Readdir(100)
if err != nil {
return
}