From 7b89b36e37979adf36c34efd4c0351edd75f1be7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 18:54:43 +0000 Subject: [PATCH] add benchmarks --- service_test.go | 166 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 26 deletions(-) diff --git a/service_test.go b/service_test.go index db4d8c42..5c2dba3f 100644 --- a/service_test.go +++ b/service_test.go @@ -2,65 +2,179 @@ package micro import ( "context" + "errors" "sync" "testing" + glog "github.com/go-log/log" + "github.com/micro/go-log" + "github.com/micro/go-micro/client" "github.com/micro/go-micro/registry/memory" proto "github.com/micro/go-micro/server/debug/proto" ) -func TestService(t *testing.T) { - var wg sync.WaitGroup +func testShutdown(wg *sync.WaitGroup, cancel func()) { + // add 1 wg.Add(1) + // shutdown the service + cancel() + // wait for stop + wg.Wait() +} - // cancellation context - ctx, cancel := context.WithCancel(context.Background()) +func testService(ctx context.Context, wg *sync.WaitGroup, name string) Service { + // set no op logger + log.SetLogger(glog.DefaultLogger) + + // add self + wg.Add(1) r := memory.NewRegistry() r.(*memory.Registry).Setup() // create service - service := NewService( - Name("test.service"), + return NewService( + Name(name), Context(ctx), Registry(r), AfterStart(func() error { wg.Done() return nil }), + AfterStop(func() error { + wg.Done() + return nil + }), + ) +} + +func testRequest(ctx context.Context, c client.Client, name string) error { + // test call debug + req := c.NewRequest( + name, + "Debug.Health", + new(proto.HealthRequest), ) - // we can't test service.Init as it parses the command line - // service.Init() + rsp := new(proto.HealthResponse) + + err := c.Call(context.TODO(), req, rsp) + if err != nil { + return err + } + + if rsp.Status != "ok" { + return errors.New("service response: " + rsp.Status) + } + + return nil +} + +// TestService tests running and calling a service +func TestService(t *testing.T) { + // waitgroup for server start + var wg sync.WaitGroup + + // cancellation context + ctx, cancel := context.WithCancel(context.Background()) + + // start test server + service := testService(ctx, &wg, "test.service") - // run service go func() { - // wait for start + // wait for service to start wg.Wait() - // test call debug - req := service.Client().NewRequest( - "test.service", - "Debug.Health", - new(proto.HealthRequest), - ) - - rsp := new(proto.HealthResponse) - - err := service.Client().Call(context.TODO(), req, rsp) - if err != nil { + // make a test call + if err := testRequest(ctx, service.Client(), "test.service"); err != nil { t.Fatal(err) } - if rsp.Status != "ok" { - t.Fatalf("service response: %s", rsp.Status) - } - // shutdown the service - cancel() + testShutdown(&wg, cancel) }() + // start service if err := service.Run(); err != nil { t.Fatal(err) } } + +func benchmarkService(b *testing.B, n int, name string) { + // stop the timer + b.StopTimer() + + // waitgroup for server start + var wg sync.WaitGroup + + // cancellation context + ctx, cancel := context.WithCancel(context.Background()) + + // create test server + service := testService(ctx, &wg, name) + + // start the server + go func() { + if err := service.Run(); err != nil { + b.Fatal(err) + } + }() + + // wait for service to start + wg.Wait() + + // make a test call to warm the cache + for i := 0; i < 10; i++ { + if err := testRequest(ctx, service.Client(), name); err != nil { + b.Fatal(err) + } + } + + // start the timer + b.StartTimer() + + // number of iterations + for i := 0; i < b.N; i++ { + // for concurrency + for j := 0; j < n; j++ { + wg.Add(1) + + go func() { + err := testRequest(ctx, service.Client(), name) + wg.Done() + if err != nil { + b.Fatal(err) + } + }() + } + + // wait for test completion + wg.Wait() + } + + // stop the timer + b.StopTimer() + + // shutdown service + testShutdown(&wg, cancel) +} + +func BenchmarkService1(b *testing.B) { + benchmarkService(b, 1, "test.service.1") +} + +func BenchmarkService8(b *testing.B) { + benchmarkService(b, 8, "test.service.8") +} + +func BenchmarkService16(b *testing.B) { + benchmarkService(b, 16, "test.service.16") +} + +func BenchmarkService32(b *testing.B) { + benchmarkService(b, 32, "test.service.32") +} + +func BenchmarkService64(b *testing.B) { + benchmarkService(b, 64, "test.service.64") +}