veyron/runtimes/google/ipc/benchmarks: IPC benchmarks.

Adds a few benchmarks for the IPC code. Some initial numbers are in the
README file.

Change-Id: I1e06701b900e930d53ec911e3528f59d596d817c
diff --git a/runtimes/google/ipc/benchmarks/README.txt b/runtimes/google/ipc/benchmarks/README.txt
new file mode 100644
index 0000000..861911b
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/README.txt
@@ -0,0 +1,130 @@
+This directory contains code uses to measure the performance of the Veyron IPC
+stack.
+
+The ipc_test.go file uses GO's testing package to run benchmarks. Each
+benchmark involves one server and one client. The server has two very simple
+methods that echo the data received from the client back to the client.
+
+client ---- Echo(payload) ----> server
+client <--- return payload ---- server
+
+There are two versions of the Echo method:
+ - Echo(payload []byte) ([]byte], error)
+ - EchoStream() <[]byte,[]byte> error
+
+The first benchmarks use the non-streaming version of Echo with a varying
+payload size. The other benchmarks use the streaming version with varying
+number of chunks and payload sizes.
+
+All these benchmarks create a VC before measurements begin. So, the VC creation
+overhead is excluded.
+
+On a ThinkPad X1 Carbon (2 × Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz), we get:
+
+$ $VEYRON_ROOT/veyron/scripts/build/go test -test.bench=. -test.cpu=1 \
+	-test.benchtime=5s veyron/runtimes/google/ipc/benchmarks 2> /dev/null
+PASS
+Benchmark____1B	   10000	    545077 ns/op
+Benchmark___10B	   10000	    587312 ns/op
+Benchmark__100B	   10000	    523019 ns/op
+Benchmark___1KB	   10000	    605235 ns/op
+Benchmark__10KB	   10000	    957467 ns/op
+Benchmark_100KB	    5000	   4101891 ns/op
+Benchmark_N_RPCs____1_chunk_____1B	   10000	    554063 ns/op
+Benchmark_N_RPCs____1_chunk____10B	   10000	    551424 ns/op
+Benchmark_N_RPCs____1_chunk___100B	   10000	    538308 ns/op
+Benchmark_N_RPCs____1_chunk____1KB	   10000	    585579 ns/op
+Benchmark_N_RPCs____1_chunk___10KB	   10000	    904789 ns/op
+Benchmark_N_RPCs___10_chunks___1KB	   10000	   1460984 ns/op
+Benchmark_N_RPCs__100_chunks___1KB	    1000	   8491514 ns/op
+Benchmark_N_RPCs_1000_chunks___1KB	     100	 105269359 ns/op
+Benchmark_1_RPC_N_chunks_____1B	  200000	    763769 ns/op
+Benchmark_1_RPC_N_chunks____10B	  100000	    583134 ns/op
+Benchmark_1_RPC_N_chunks___100B	  100000	     80849 ns/op
+Benchmark_1_RPC_N_chunks____1KB	  100000	     88820 ns/op
+Benchmark_1_RPC_N_chunks___10KB	   50000	    361596 ns/op
+Benchmark_1_RPC_N_chunks__100KB	    5000	   3127193 ns/op
+ok  	veyron/runtimes/google/ipc/benchmarks	525.095s
+
+
+The Benchmark_Simple_____1KB line shows that it takes an average of 0.605 ms to
+execute a simple Echo RPC with a 1 KB payload.
+
+The Benchmark_N_RPCs____1_chunk____1KB line shows that a streaming RPC with the
+same payload (i.e. 1 chunk of 1 KB) takes about 0.586 ms on average.
+
+And Benchmark_1_RPC_N_chunks____1KB shows that sending a stream of 1 KB chunks
+takes an average of 0.088 ms per chunk.
+
+
+Running the client and server as separate processes.
+
+In this case, we can see the cost of name resolution, creating the VC, etc. in
+the first RPC.
+
+$ $VEYRON_ROOT/veyron/go/bin/bmserver --address=localhost:8888 --acl='{"*":"A"}'
+
+(In a different shell)
+$ $VEYRON_ROOT/veyron/go/bin/bmclient --server=/localhost:8888 --count=10 \
+	--payload_size=1000
+CallEcho 0 64133467
+CallEcho 1 766223
+CallEcho 2 703860
+CallEcho 3 697590
+CallEcho 4 601134
+CallEcho 5 601142
+CallEcho 6 624079
+CallEcho 7 644664
+CallEcho 8 605195
+CallEcho 9 637037
+
+It took about 64 ms to execute the first RPC, and then 0.60-0.70 ms to execute
+the next ones.
+
+
+On a Raspberry Pi, everything is much slower. The same tests show the following
+results:
+
+$ ./benchmarks.test -test.bench=. -test.cpu=1 -test.benchtime=5s 2>/dev/null
+PASS
+Benchmark____1B             500          21316148 ns/op
+Benchmark___10B             500          23304638 ns/op
+Benchmark__100B             500          21860446 ns/op
+Benchmark___1KB             500          24000346 ns/op
+Benchmark__10KB             200          37530575 ns/op
+Benchmark_100KB             100         136243310 ns/op
+Benchmark_N_RPCs____1_chunk_____1B           500          19957506 ns/op
+Benchmark_N_RPCs____1_chunk____10B           500          22868392 ns/op
+Benchmark_N_RPCs____1_chunk___100B           500          19635412 ns/op
+Benchmark_N_RPCs____1_chunk____1KB           500          22572190 ns/op
+Benchmark_N_RPCs____1_chunk___10KB           500          37570948 ns/op
+Benchmark_N_RPCs___10_chunks___1KB           100          51670740 ns/op
+Benchmark_N_RPCs__100_chunks___1KB            50         364938740 ns/op
+Benchmark_N_RPCs_1000_chunks___1KB             2        3586374500 ns/op
+Benchmark_1_RPC_N_chunks_____1B    10000           1034042 ns/op
+Benchmark_1_RPC_N_chunks____10B     5000           1894875 ns/op
+Benchmark_1_RPC_N_chunks___100B     5000           2857289 ns/op
+Benchmark_1_RPC_N_chunks____1KB     5000           6465839 ns/op
+Benchmark_1_RPC_N_chunks___10KB      100          80019430 ns/op
+Benchmark_1_RPC_N_chunks__100KB Killed
+
+The simple 1 KB RPCs take an average of 24 ms. The streaming equivalent takes
+about 22 ms, and streaming many 1 KB chunks takes about 6.5 ms per chunk.
+
+
+$ ./bmserver --address=localhost:8888 --acl='{"*":"A"}'
+
+$ ./bmclient --server=/localhost:8888 --count=10 --payload_size=1000
+CallEcho 0 2573406000
+CallEcho 1 44669000
+CallEcho 2 54442000
+CallEcho 3 33934000
+CallEcho 4 47985000
+CallEcho 5 61324000
+CallEcho 6 51654000
+CallEcho 7 47043000
+CallEcho 8 44995000
+CallEcho 9 53166000
+
+On the pi, the first RPC takes ~2.5 sec to execute.
+
diff --git a/runtimes/google/ipc/benchmarks/bmclient/main.go b/runtimes/google/ipc/benchmarks/bmclient/main.go
new file mode 100644
index 0000000..16c34c5
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/bmclient/main.go
@@ -0,0 +1,27 @@
+// a simple command-line tool to run the benchmark client.
+package main
+
+import (
+	"flag"
+	"os"
+
+	"veyron/runtimes/google/ipc/benchmarks"
+
+	"veyron2/rt"
+)
+
+var (
+	server      = flag.String("server", "", "veyron name of the server to connect to")
+	count       = flag.Int("count", 1, "number of RPCs to send")
+	chunkCount  = flag.Int("chunk_count", 0, "number of stream chunks to send")
+	payloadSize = flag.Int("payload_size", 32, "the size of the payload")
+)
+
+func main() {
+	rt.Init()
+	if *chunkCount == 0 {
+		benchmarks.CallEcho(*server, *count, *payloadSize, os.Stdout)
+	} else {
+		benchmarks.CallEchoStream(*server, *count, *chunkCount, *payloadSize, os.Stdout)
+	}
+}
diff --git a/runtimes/google/ipc/benchmarks/bmserver/main.go b/runtimes/google/ipc/benchmarks/bmserver/main.go
new file mode 100644
index 0000000..017ad69
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/bmserver/main.go
@@ -0,0 +1,25 @@
+// a simple command-line tool to run the benchmark server.
+package main
+
+import (
+	"flag"
+
+	"veyron/lib/signals"
+	"veyron/runtimes/google/ipc/benchmarks"
+
+	"veyron2/rt"
+	"veyron2/vlog"
+)
+
+var (
+	address  = flag.String("address", ":0", "address to listen on")
+	protocol = flag.String("protocol", "tcp", "protocol to listen on")
+)
+
+func main() {
+	rt.Init()
+	addr, stop := benchmarks.StartServer(*protocol, *address)
+	vlog.Infof("Listening on %s", addr)
+	defer stop()
+	<-signals.ShutdownOnSignals()
+}
diff --git a/runtimes/google/ipc/benchmarks/client.go b/runtimes/google/ipc/benchmarks/client.go
new file mode 100644
index 0000000..8117e8f
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/client.go
@@ -0,0 +1,101 @@
+package benchmarks
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"time"
+
+	"veyron2"
+	"veyron2/rt"
+	"veyron2/vlog"
+)
+
+// CallEcho calls the Echo method 'iterations' times with the given payload
+// size, and optionally logs the result.
+func CallEcho(address string, iterations, payloadSize int, log io.Writer) {
+	payload := make([]byte, payloadSize)
+	for _, i := range payload {
+		payload[i] = byte(i & 0xff)
+	}
+
+	stub, err := BindBenchmark(address)
+	if err != nil {
+		vlog.Fatalf("BindBenchmark(%q) failed: %v", address, err)
+	}
+
+	for i := 0; i < iterations; i++ {
+		start := time.Now()
+		result, err := stub.Echo(rt.R().TODOContext(), payload)
+		elapsed := time.Since(start)
+		if err != nil {
+			vlog.Fatalf("Echo failed: %v", err)
+		}
+		if !bytes.Equal(payload, result) {
+			vlog.Fatalf("Echo return different payload: got %v, expected %v", result, payload)
+		}
+		if log != nil {
+			log.Write([]byte(fmt.Sprintf("CallEcho %d %d\n", i, elapsed)))
+		}
+	}
+}
+
+// CallEchoStream calls the EchoStream method 'rpcCount' times. Each iteration
+// sends 'messageCount' messages on the stream and receives the same number
+// back. Each message has the given payload size. Optionally logs the result.
+func CallEchoStream(address string, rpcCount, messageCount, payloadSize int, log io.Writer) {
+	payload := make([]byte, payloadSize)
+	for _, i := range payload {
+		payload[i] = byte(i & 0xff)
+	}
+
+	stub, err := BindBenchmark(address)
+	if err != nil {
+		vlog.Fatalf("BindBenchmark(%q) failed: %v", address, err)
+	}
+
+	for i := 0; i < rpcCount; i++ {
+		start := time.Now()
+		stream, err := stub.EchoStream(rt.R().TODOContext(), veyron2.CallTimeout(time.Hour))
+		if err != nil {
+			vlog.Fatalf("EchoStream failed: %v", err)
+		}
+		done := make(chan error, 1)
+		go func() {
+			for {
+				chunk, err := stream.Recv()
+				if err == io.EOF {
+					done <- nil
+					return
+				}
+				if err != nil {
+					done <- err
+					return
+				}
+				if !bytes.Equal(payload, chunk) {
+					done <- fmt.Errorf("Recv got different payload: got %v, expected %v", chunk, payload)
+					return
+				}
+			}
+		}()
+		for j := 0; j < messageCount; j++ {
+			if err = stream.Send(payload); err != nil {
+				vlog.Fatalf("Send failed: %v", err)
+			}
+		}
+		if err = stream.CloseSend(); err != nil {
+			vlog.Fatalf("CloseSend() failed: %v", err)
+		}
+		if err = <-done; err != nil {
+			vlog.Fatalf("%v", err)
+		}
+
+		if err = stream.Finish(); err != nil {
+			vlog.Fatalf("Finish failed: %v", err)
+		}
+		elapsed := time.Since(start)
+		if log != nil {
+			log.Write([]byte(fmt.Sprintf("CallEchoStream %d %d\n", i, elapsed)))
+		}
+	}
+}
diff --git a/runtimes/google/ipc/benchmarks/ipc_test.go b/runtimes/google/ipc/benchmarks/ipc_test.go
new file mode 100644
index 0000000..411869f
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/ipc_test.go
@@ -0,0 +1,109 @@
+package benchmarks_test
+
+import (
+	"testing"
+
+	"veyron/runtimes/google/ipc/benchmarks"
+
+	"veyron2/rt"
+)
+
+func init() {
+	rt.Init()
+}
+
+func RunBenchmark(b *testing.B, payloadSize int) {
+	address, stop := benchmarks.StartServer("tcp", "127.0.0.1:0")
+	defer stop()
+	benchmarks.CallEcho(address, 1, 1, nil) // Create VC
+	b.ResetTimer()
+	benchmarks.CallEcho(address, b.N, payloadSize, nil)
+}
+
+func RunStreamBenchmark(b *testing.B, rpcCount, messageCount, payloadSize int) {
+	address, stop := benchmarks.StartServer("tcp", "127.0.0.1:0")
+	defer stop()
+	benchmarks.CallEchoStream(address, 1, 1, 1, nil) // Create VC
+	b.ResetTimer()
+	benchmarks.CallEchoStream(address, rpcCount, messageCount, payloadSize, nil)
+}
+
+func Benchmark____1B(b *testing.B) {
+	RunBenchmark(b, 1)
+}
+
+func Benchmark___10B(b *testing.B) {
+	RunBenchmark(b, 10)
+}
+
+func Benchmark__100B(b *testing.B) {
+	RunBenchmark(b, 100)
+}
+
+func Benchmark___1KB(b *testing.B) {
+	RunBenchmark(b, 1000)
+}
+
+func Benchmark__10KB(b *testing.B) {
+	RunBenchmark(b, 10000)
+}
+
+func Benchmark_100KB(b *testing.B) {
+	RunBenchmark(b, 100000)
+}
+
+func Benchmark_N_RPCs____1_chunk_____1B(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1, 1)
+}
+
+func Benchmark_N_RPCs____1_chunk____10B(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1, 10)
+}
+
+func Benchmark_N_RPCs____1_chunk___100B(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1, 100)
+}
+
+func Benchmark_N_RPCs____1_chunk____1KB(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1, 1000)
+}
+
+func Benchmark_N_RPCs____1_chunk___10KB(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1, 10000)
+}
+
+func Benchmark_N_RPCs___10_chunks___1KB(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 10, 1000)
+}
+
+func Benchmark_N_RPCs__100_chunks___1KB(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 100, 1000)
+}
+
+func Benchmark_N_RPCs_1000_chunks___1KB(b *testing.B) {
+	RunStreamBenchmark(b, b.N, 1000, 1000)
+}
+
+func Benchmark_1_RPC_N_chunks_____1B(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 1)
+}
+
+func Benchmark_1_RPC_N_chunks____10B(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 10)
+}
+
+func Benchmark_1_RPC_N_chunks___100B(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 100)
+}
+
+func Benchmark_1_RPC_N_chunks____1KB(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 1000)
+}
+
+func Benchmark_1_RPC_N_chunks___10KB(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 10000)
+}
+
+func Benchmark_1_RPC_N_chunks__100KB(b *testing.B) {
+	RunStreamBenchmark(b, 1, b.N, 100000)
+}
diff --git a/runtimes/google/ipc/benchmarks/server.go b/runtimes/google/ipc/benchmarks/server.go
new file mode 100644
index 0000000..d585d72
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/server.go
@@ -0,0 +1,57 @@
+package benchmarks
+
+import (
+	"io"
+
+	sflag "veyron/security/flag"
+
+	"veyron2/ipc"
+	"veyron2/naming"
+	"veyron2/rt"
+	"veyron2/vlog"
+)
+
+type impl struct {
+}
+
+func (i *impl) Echo(ctx ipc.ServerContext, payload []byte) ([]byte, error) {
+	return payload, nil
+}
+
+func (i *impl) EchoStream(ctx ipc.ServerContext, stream BenchmarkServiceEchoStreamStream) error {
+	for {
+		chunk, err := stream.Recv()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return err
+		}
+		if err := stream.Send(chunk); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// StartServer starts a server that implements the Benchmark service. The
+// server listens to the given protocol and address, and returns the veyron
+// address of the server and a callback function to stop the server.
+func StartServer(protocol, address string) (string, func()) {
+	server, err := rt.R().NewServer()
+	if err != nil {
+		vlog.Fatalf("NewServer failed: %v", err)
+	}
+	if err := server.Register("", ipc.SoloDispatcher(NewServerBenchmark(&impl{}), sflag.NewAuthorizerOrDie())); err != nil {
+		vlog.Fatalf("Register failed: %v", err)
+	}
+	ep, err := server.Listen(protocol, address)
+	if err != nil {
+		vlog.Fatalf("Listen failed: %v", err)
+	}
+	return naming.JoinAddressName(ep.String(), ""), func() {
+		if err := server.Stop(); err != nil {
+			vlog.Fatalf("Stop() failed: %v", err)
+		}
+	}
+}
diff --git a/runtimes/google/ipc/benchmarks/service.vdl b/runtimes/google/ipc/benchmarks/service.vdl
new file mode 100644
index 0000000..ad0afcf
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/service.vdl
@@ -0,0 +1,10 @@
+// package benchmark provides simple tools to measure the performance of the
+// IPC system.
+package benchmarks
+
+type Benchmark interface {
+  // Echo returns the payload that it receives.
+  Echo(Payload []byte) ([]byte, error)
+  // EchoStream returns the payload that it receives via the stream.
+  EchoStream() stream<[]byte,[]byte> error
+}
diff --git a/runtimes/google/ipc/benchmarks/service.vdl.go b/runtimes/google/ipc/benchmarks/service.vdl.go
new file mode 100644
index 0000000..371285d
--- /dev/null
+++ b/runtimes/google/ipc/benchmarks/service.vdl.go
@@ -0,0 +1,293 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: service.vdl
+
+// package benchmark provides simple tools to measure the performance of the
+// IPC system.
+package benchmarks
+
+import (
+	// The non-user imports are prefixed with "_gen_" to prevent collisions.
+	_gen_veyron2 "veyron2"
+	_gen_context "veyron2/context"
+	_gen_ipc "veyron2/ipc"
+	_gen_naming "veyron2/naming"
+	_gen_rt "veyron2/rt"
+	_gen_vdl "veyron2/vdl"
+	_gen_wiretype "veyron2/wiretype"
+)
+
+// Benchmark is the interface the client binds and uses.
+// Benchmark_ExcludingUniversal is the interface without internal framework-added methods
+// to enable embedding without method collisions.  Not to be used directly by clients.
+type Benchmark_ExcludingUniversal interface {
+	// Echo returns the payload that it receives.
+	Echo(ctx _gen_context.T, Payload []byte, opts ..._gen_ipc.CallOpt) (reply []byte, err error)
+	// EchoStream returns the payload that it receives via the stream.
+	EchoStream(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply BenchmarkEchoStreamStream, err error)
+}
+type Benchmark interface {
+	_gen_ipc.UniversalServiceMethods
+	Benchmark_ExcludingUniversal
+}
+
+// BenchmarkService is the interface the server implements.
+type BenchmarkService interface {
+
+	// Echo returns the payload that it receives.
+	Echo(context _gen_ipc.ServerContext, Payload []byte) (reply []byte, err error)
+	// EchoStream returns the payload that it receives via the stream.
+	EchoStream(context _gen_ipc.ServerContext, stream BenchmarkServiceEchoStreamStream) (err error)
+}
+
+// BenchmarkEchoStreamStream is the interface for streaming responses of the method
+// EchoStream in the service interface Benchmark.
+type BenchmarkEchoStreamStream interface {
+
+	// Send places the item onto the output stream, blocking if there is no buffer
+	// space available.
+	Send(item []byte) error
+
+	// CloseSend indicates to the server that no more items will be sent; server
+	// Recv calls will receive io.EOF after all sent items.  Subsequent calls to
+	// Send on the client will fail.  This is an optional call - it's used by
+	// streaming clients that need the server to receive the io.EOF terminator.
+	CloseSend() error
+
+	// Recv returns the next item in the input stream, blocking until
+	// an item is available.  Returns io.EOF to indicate graceful end of input.
+	Recv() (item []byte, err error)
+
+	// Finish closes the stream and returns the positional return values for
+	// call.
+	Finish() (err error)
+
+	// Cancel cancels the RPC, notifying the server to stop processing.
+	Cancel()
+}
+
+// Implementation of the BenchmarkEchoStreamStream interface that is not exported.
+type implBenchmarkEchoStreamStream struct {
+	clientCall _gen_ipc.Call
+}
+
+func (c *implBenchmarkEchoStreamStream) Send(item []byte) error {
+	return c.clientCall.Send(item)
+}
+
+func (c *implBenchmarkEchoStreamStream) CloseSend() error {
+	return c.clientCall.CloseSend()
+}
+
+func (c *implBenchmarkEchoStreamStream) Recv() (item []byte, err error) {
+	err = c.clientCall.Recv(&item)
+	return
+}
+
+func (c *implBenchmarkEchoStreamStream) Finish() (err error) {
+	if ierr := c.clientCall.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (c *implBenchmarkEchoStreamStream) Cancel() {
+	c.clientCall.Cancel()
+}
+
+// BenchmarkServiceEchoStreamStream is the interface for streaming responses of the method
+// EchoStream in the service interface Benchmark.
+type BenchmarkServiceEchoStreamStream interface {
+	// Send places the item onto the output stream, blocking if there is no buffer
+	// space available.
+	Send(item []byte) error
+
+	// Recv fills itemptr with the next item in the input stream, blocking until
+	// an item is available.  Returns io.EOF to indicate graceful end of input.
+	Recv() (item []byte, err error)
+}
+
+// Implementation of the BenchmarkServiceEchoStreamStream interface that is not exported.
+type implBenchmarkServiceEchoStreamStream struct {
+	serverCall _gen_ipc.ServerCall
+}
+
+func (s *implBenchmarkServiceEchoStreamStream) Send(item []byte) error {
+	return s.serverCall.Send(item)
+}
+
+func (s *implBenchmarkServiceEchoStreamStream) Recv() (item []byte, err error) {
+	err = s.serverCall.Recv(&item)
+	return
+}
+
+// BindBenchmark returns the client stub implementing the Benchmark
+// interface.
+//
+// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
+// global Runtime is used.
+func BindBenchmark(name string, opts ..._gen_ipc.BindOpt) (Benchmark, error) {
+	var client _gen_ipc.Client
+	switch len(opts) {
+	case 0:
+		client = _gen_rt.R().Client()
+	case 1:
+		switch o := opts[0].(type) {
+		case _gen_veyron2.Runtime:
+			client = o.Client()
+		case _gen_ipc.Client:
+			client = o
+		default:
+			return nil, _gen_vdl.ErrUnrecognizedOption
+		}
+	default:
+		return nil, _gen_vdl.ErrTooManyOptionsToBind
+	}
+	stub := &clientStubBenchmark{client: client, name: name}
+
+	return stub, nil
+}
+
+// NewServerBenchmark creates a new server stub.
+//
+// It takes a regular server implementing the BenchmarkService
+// interface, and returns a new server stub.
+func NewServerBenchmark(server BenchmarkService) interface{} {
+	return &ServerStubBenchmark{
+		service: server,
+	}
+}
+
+// clientStubBenchmark implements Benchmark.
+type clientStubBenchmark struct {
+	client _gen_ipc.Client
+	name   string
+}
+
+func (__gen_c *clientStubBenchmark) Echo(ctx _gen_context.T, Payload []byte, opts ..._gen_ipc.CallOpt) (reply []byte, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Echo", []interface{}{Payload}, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubBenchmark) EchoStream(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply BenchmarkEchoStreamStream, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "EchoStream", nil, opts...); err != nil {
+		return
+	}
+	reply = &implBenchmarkEchoStreamStream{clientCall: call}
+	return
+}
+
+func (__gen_c *clientStubBenchmark) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubBenchmark) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubBenchmark) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+// ServerStubBenchmark wraps a server that implements
+// BenchmarkService and provides an object that satisfies
+// the requirements of veyron2/ipc.ReflectInvoker.
+type ServerStubBenchmark struct {
+	service BenchmarkService
+}
+
+func (__gen_s *ServerStubBenchmark) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
+	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
+	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
+	// This will change when it is replaced with Signature().
+	switch method {
+	case "Echo":
+		return []interface{}{}, nil
+	case "EchoStream":
+		return []interface{}{}, nil
+	default:
+		return nil, nil
+	}
+}
+
+func (__gen_s *ServerStubBenchmark) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
+	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
+	result.Methods["Echo"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{
+			{Name: "Payload", Type: 66},
+		},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 66},
+			{Name: "", Type: 67},
+		},
+	}
+	result.Methods["EchoStream"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 67},
+		},
+		InStream:  66,
+		OutStream: 66,
+	}
+
+	result.TypeDefs = []_gen_vdl.Any{
+		_gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, _gen_wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
+
+	return result, nil
+}
+
+func (__gen_s *ServerStubBenchmark) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
+	if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
+		return unresolver.UnresolveStep(call)
+	}
+	if call.Server() == nil {
+		return
+	}
+	var published []string
+	if published, err = call.Server().Published(); err != nil || published == nil {
+		return
+	}
+	reply = make([]string, len(published))
+	for i, p := range published {
+		reply[i] = _gen_naming.Join(p, call.Name())
+	}
+	return
+}
+
+func (__gen_s *ServerStubBenchmark) Echo(call _gen_ipc.ServerCall, Payload []byte) (reply []byte, err error) {
+	reply, err = __gen_s.service.Echo(call, Payload)
+	return
+}
+
+func (__gen_s *ServerStubBenchmark) EchoStream(call _gen_ipc.ServerCall) (err error) {
+	stream := &implBenchmarkServiceEchoStreamStream{serverCall: call}
+	err = __gen_s.service.EchoStream(call, stream)
+	return
+}