├── Makefile ├── README.md ├── client.go ├── conn.go ├── echo.pb.go ├── echo.proto ├── go.mod ├── go.sum ├── rpc_test.go ├── server.crt ├── server.go ├── server.key ├── tools.go ├── wire.pb.go └── wire.proto /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Cockroach Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. See the License for the specific language governing 13 | # permissions and limitations under the License. See the AUTHORS file 14 | # for names of contributors. 15 | # 16 | # Author: Tamir Duberstein (tamird@gmail.com) 17 | 18 | PROTOS := $(sort $(wildcard *.proto)) 19 | 20 | all: 21 | protoc --proto_path=. --gogofaster_out=plugins=grpc:. $(PROTOS) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rpc-bench 2 | ========= 3 | 4 | Currently covered: 5 | - [grpc-go](https://github.com/grpc/grpc-go) using (*Server).Serve 6 | - [grpc-go](https://github.com/grpc/grpc-go) using (*Server).ServeHTTP 7 | - [net/rpc](http://godoc.org/net/rpc) 8 | - [net/rpc](http://godoc.org/net/rpc) + [protobuf](https://github.com/gogo/protobuf) codec 9 | - [net/http](http://godoc.org/net/http) + [protobuf](https://github.com/gogo/protobuf) on the wire 10 | - [golang.org/x/net/http2](https://godoc.org/golang.org/x/net/http2) + [protobuf](https://github.com/gogo/protobuf) on the wire 11 | 12 | results (2020-04-18) 13 | ==================== 14 | Run with `go test -benchmem -benchtime 5s -count 5 -bench . -timeout 1h | tee results && benchstat results` 15 | 16 | ## go version go1.14 linux/amd64 17 | 18 | ``` 19 | name time/op 20 | GRPCServe_1K-36 62.6µs ± 7% 21 | GRPCServe_64K-36 263µs ± 2% 22 | GRPCServe_Stream_1K-36 31.1µs ± 3% 23 | GRPCServe_Stream_64k-36 264µs ± 2% 24 | GRPCServeHTTP_1K-36 262µs ± 2% 25 | GRPCServeHTTP_64K-36 642µs ± 2% 26 | GRPCServeHTTP_Stream_1K-36 42.3µs ± 2% 27 | GRPCServeHTTP_Stream_64k-36 538µs ± 1% 28 | GobRPC_1K-36 29.7µs ± 3% 29 | GobRPC_64K-36 204µs ± 1% 30 | ProtoRPC_1K-36 27.3µs ± 2% 31 | ProtoRPC_64K-36 221µs ± 1% 32 | ProtoHTTP1_1K-36 65.2µs ±15% 33 | ProtoHTTP1_64K-36 172µs ± 9% 34 | ProtoHTTP2_1K-36 115µs ±24% 35 | ProtoHTTP2_64K-36 750µs ± 3% 36 | 37 | name speed 38 | GRPCServe_1K-36 32.7MB/s ± 7% 39 | GRPCServe_64K-36 499MB/s ± 2% 40 | GRPCServe_Stream_1K-36 65.8MB/s ± 3% 41 | GRPCServe_Stream_64k-36 497MB/s ± 2% 42 | GRPCServeHTTP_1K-36 7.81MB/s ± 2% 43 | GRPCServeHTTP_64K-36 204MB/s ± 2% 44 | GRPCServeHTTP_Stream_1K-36 48.5MB/s ± 2% 45 | GRPCServeHTTP_Stream_64k-36 244MB/s ± 1% 46 | GobRPC_1K-36 69.0MB/s ± 3% 47 | GobRPC_64K-36 643MB/s ± 1% 48 | ProtoRPC_1K-36 75.0MB/s ± 2% 49 | ProtoRPC_64K-36 594MB/s ± 1% 50 | ProtoHTTP1_1K-36 31.6MB/s ±14% 51 | ProtoHTTP1_64K-36 763MB/s ± 9% 52 | ProtoHTTP2_1K-36 18.0MB/s ±20% 53 | ProtoHTTP2_64K-36 175MB/s ± 3% 54 | 55 | name alloc/op 56 | GRPCServe_1K-36 17.7kB ± 0% 57 | GRPCServe_64K-36 489kB ± 0% 58 | GRPCServe_Stream_1K-36 10.1kB ± 0% 59 | GRPCServe_Stream_64k-36 484kB ± 0% 60 | GRPCServeHTTP_1K-36 37.4kB ± 0% 61 | GRPCServeHTTP_64K-36 563kB ± 0% 62 | GRPCServeHTTP_Stream_1K-36 10.2kB ± 0% 63 | GRPCServeHTTP_Stream_64k-36 546kB ± 0% 64 | GobRPC_1K-36 2.46kB ± 0% 65 | GobRPC_64K-36 132kB ± 0% 66 | ProtoRPC_1K-36 2.43kB ± 0% 67 | ProtoRPC_64K-36 279kB ± 0% 68 | ProtoHTTP1_1K-36 56.8kB ± 1% 69 | ProtoHTTP1_64K-36 904kB ± 0% 70 | ProtoHTTP2_1K-36 63.6kB ± 2% 71 | ProtoHTTP2_64K-36 1.02MB ±10% 72 | 73 | name allocs/op 74 | GRPCServe_1K-36 154 ± 0% 75 | GRPCServe_64K-36 167 ± 0% 76 | GRPCServe_Stream_1K-36 29.0 ± 0% 77 | GRPCServe_Stream_64k-36 52.0 ± 0% 78 | GRPCServeHTTP_1K-36 212 ± 0% 79 | GRPCServeHTTP_64K-36 326 ± 1% 80 | GRPCServeHTTP_Stream_1K-36 36.0 ± 0% 81 | GRPCServeHTTP_Stream_64k-36 168 ± 1% 82 | GobRPC_1K-36 14.0 ± 0% 83 | GobRPC_64K-36 20.0 ± 0% 84 | ProtoRPC_1K-36 12.0 ± 0% 85 | ProtoRPC_64K-36 18.0 ± 0% 86 | ProtoHTTP1_1K-36 634 ± 1% 87 | ProtoHTTP1_64K-36 699 ± 1% 88 | ProtoHTTP2_1K-36 114 ± 0% 89 | ProtoHTTP2_64K-36 213 ± 0% 90 | ``` 91 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | // 16 | // Author: Peter Mattis (peter@cockroachlabs.com) 17 | 18 | // Copyright 2013 . All rights reserved. 19 | // Use of this source code is governed by a BSD-style 20 | // license that can be found in the LICENSE file. 21 | 22 | package rpcbench 23 | 24 | import ( 25 | "bufio" 26 | "bytes" 27 | "fmt" 28 | "io" 29 | "net/rpc" 30 | 31 | "github.com/gogo/protobuf/proto" 32 | ) 33 | 34 | type clientCodec struct { 35 | baseConn 36 | 37 | methods map[string]int32 38 | 39 | // temporary work space 40 | reqBodyBuf bytes.Buffer 41 | reqHeaderBuf bytes.Buffer 42 | reqHeader RequestHeader 43 | respHeader ResponseHeader 44 | } 45 | 46 | // NewClientCodec returns a new rpc.ClientCodec using Protobuf-RPC on conn. 47 | func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec { 48 | return &clientCodec{ 49 | baseConn: baseConn{ 50 | r: bufio.NewReader(conn), 51 | w: bufio.NewWriter(conn), 52 | c: conn, 53 | }, 54 | methods: make(map[string]int32), 55 | } 56 | } 57 | 58 | func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error { 59 | var request proto.Message 60 | if param != nil { 61 | var ok bool 62 | if request, ok = param.(proto.Message); !ok { 63 | return fmt.Errorf( 64 | "protorpc.ClientCodec.WriteRequest: %T does not implement proto.Message", 65 | param, 66 | ) 67 | } 68 | } 69 | 70 | if err := c.writeRequest(r, request); err != nil { 71 | return err 72 | } 73 | return c.w.Flush() 74 | } 75 | 76 | func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error { 77 | if err := c.readResponseHeader(&c.respHeader); err != nil { 78 | return err 79 | } 80 | 81 | r.Seq = c.respHeader.Id 82 | r.ServiceMethod = c.respHeader.Method 83 | r.Error = c.respHeader.Error 84 | return nil 85 | } 86 | 87 | func (c *clientCodec) ReadResponseBody(x interface{}) error { 88 | var response proto.Message 89 | if x != nil { 90 | var ok bool 91 | response, ok = x.(proto.Message) 92 | if !ok { 93 | return fmt.Errorf( 94 | "protorpc.ClientCodec.ReadResponseBody: %T does not implement proto.Message", 95 | x, 96 | ) 97 | } 98 | } 99 | 100 | err := c.readResponseBody(&c.respHeader, response) 101 | if err != nil { 102 | return err 103 | } 104 | 105 | c.respHeader.Reset() 106 | return nil 107 | } 108 | 109 | func (c *clientCodec) writeRequest(r *rpc.Request, request proto.Message) error { 110 | // marshal request 111 | pbRequest, err := marshal(&c.reqBodyBuf, request) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | // generate header 117 | header := &c.reqHeader 118 | *header = RequestHeader{ 119 | Id: r.Seq, 120 | Compression: compressionType, 121 | UncompressedSize: uint32(len(pbRequest)), 122 | } 123 | if mid, ok := c.methods[r.ServiceMethod]; ok { 124 | header.MethodId = mid 125 | } else { 126 | header.Method = r.ServiceMethod 127 | header.MethodId = int32(len(c.methods)) 128 | c.methods[r.ServiceMethod] = header.MethodId 129 | } 130 | 131 | // marshal header 132 | pbHeader, err := marshal(&c.reqHeaderBuf, header) 133 | if err != nil { 134 | return err 135 | } 136 | 137 | // send header (more) 138 | if err := c.sendFrame(pbHeader); err != nil { 139 | return err 140 | } 141 | 142 | return c.sendFrame(pbRequest) 143 | } 144 | 145 | func (c *clientCodec) readResponseHeader(header *ResponseHeader) error { 146 | return c.recvProto(header, 0, protoUnmarshal) 147 | } 148 | 149 | func (c *clientCodec) readResponseBody(header *ResponseHeader, 150 | response proto.Message) error { 151 | return c.recvProto(response, header.UncompressedSize, decompressors[header.Compression]) 152 | } 153 | 154 | // NewClient returns a new rpc.Client to handle requests to the 155 | // set of services at the other end of the connection. 156 | func NewClient(conn io.ReadWriteCloser) *rpc.Client { 157 | return rpc.NewClientWithCodec(NewClientCodec(conn)) 158 | } 159 | -------------------------------------------------------------------------------- /conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | // 16 | // Author: Peter Mattis (peter@cockroachlabs.com) 17 | 18 | // Copyright 2013 . All rights reserved. 19 | // Use of this source code is governed by a BSD-style 20 | // license that can be found in the LICENSE file. 21 | 22 | package rpcbench 23 | 24 | import ( 25 | "bufio" 26 | "encoding/binary" 27 | "io" 28 | "net" 29 | 30 | "github.com/gogo/protobuf/proto" 31 | ) 32 | 33 | // LZ4 benchmarks slightly faster than Snappy for pure-RPC benchmarks, 34 | // but slightly slower than Snappy on higher level benchmarks like the 35 | // ones for the Cockroach client. 36 | const compressionType = CompressionType_NONE 37 | 38 | type decompressFunc func(src []byte, uncompressedSize uint32, m proto.Message) error 39 | 40 | var decompressors = [...]decompressFunc{ 41 | CompressionType_NONE: protoUnmarshal, 42 | // CompressionType_SNAPPY: snappyDecode, 43 | // CompressionType_LZ4: lz4Decode, 44 | } 45 | 46 | type baseConn struct { 47 | w *bufio.Writer 48 | r *bufio.Reader 49 | c io.Closer 50 | frameBuf [binary.MaxVarintLen64]byte 51 | } 52 | 53 | // Close closes the underlying connection. 54 | func (c *baseConn) Close() error { 55 | return c.c.Close() 56 | } 57 | 58 | func (c *baseConn) sendFrame(data []byte) error { 59 | // Allocate enough space for the biggest uvarint 60 | size := c.frameBuf[:] 61 | 62 | if len(data) == 0 { 63 | n := binary.PutUvarint(size, uint64(0)) 64 | return c.write(c.w, size[:n]) 65 | } 66 | 67 | // Write the size and data 68 | n := binary.PutUvarint(size, uint64(len(data))) 69 | if err := c.write(c.w, size[:n]); err != nil { 70 | return err 71 | } 72 | return c.write(c.w, data) 73 | } 74 | 75 | func (c *baseConn) write(w io.Writer, data []byte) error { 76 | for index := 0; index < len(data); { 77 | n, err := w.Write(data[index:]) 78 | if err != nil { 79 | if nerr, ok := err.(net.Error); !ok || !nerr.Temporary() { 80 | return err 81 | } 82 | } 83 | index += n 84 | } 85 | return nil 86 | } 87 | 88 | func (c *baseConn) recvProto(m proto.Message, 89 | uncompressedSize uint32, decompressor decompressFunc) error { 90 | size, err := binary.ReadUvarint(c.r) 91 | if err != nil { 92 | return err 93 | } 94 | if size == 0 { 95 | return nil 96 | } 97 | if c.r.Buffered() >= int(size) { 98 | // Parse proto directly from the buffered data. 99 | data, err := c.r.Peek(int(size)) 100 | if err != nil { 101 | return err 102 | } 103 | if err := decompressor(data, uncompressedSize, m); err != nil { 104 | return err 105 | } 106 | // TODO(pmattis): This is a hack to advance the bufio pointer by 107 | // reading into the same slice that bufio.Reader.Peek 108 | // returned. In Go 1.5 we'll be able to use 109 | // bufio.Reader.Discard. 110 | _, err = io.ReadFull(c.r, data) 111 | return err 112 | } 113 | 114 | data := make([]byte, size) 115 | if _, err := io.ReadFull(c.r, data); err != nil { 116 | return err 117 | } 118 | return decompressor(data, uncompressedSize, m) 119 | } 120 | 121 | func protoUnmarshal(src []byte, uncompressedSize uint32, msg proto.Message) error { 122 | return proto.Unmarshal(src, msg) 123 | } 124 | -------------------------------------------------------------------------------- /echo.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: echo.proto 3 | 4 | package rpcbench 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/gogo/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | io "io" 14 | math "math" 15 | math_bits "math/bits" 16 | ) 17 | 18 | // Reference imports to suppress errors if they are not otherwise used. 19 | var _ = proto.Marshal 20 | var _ = fmt.Errorf 21 | var _ = math.Inf 22 | 23 | // This is a compile-time assertion to ensure that this generated file 24 | // is compatible with the proto package it is being compiled against. 25 | // A compilation error at this line likely means your copy of the 26 | // proto package needs to be updated. 27 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 28 | 29 | type EchoRequest struct { 30 | Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` 31 | } 32 | 33 | func (m *EchoRequest) Reset() { *m = EchoRequest{} } 34 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) } 35 | func (*EchoRequest) ProtoMessage() {} 36 | func (*EchoRequest) Descriptor() ([]byte, []int) { 37 | return fileDescriptor_08134aea513e0001, []int{0} 38 | } 39 | func (m *EchoRequest) XXX_Unmarshal(b []byte) error { 40 | return m.Unmarshal(b) 41 | } 42 | func (m *EchoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 43 | if deterministic { 44 | return xxx_messageInfo_EchoRequest.Marshal(b, m, deterministic) 45 | } else { 46 | b = b[:cap(b)] 47 | n, err := m.MarshalToSizedBuffer(b) 48 | if err != nil { 49 | return nil, err 50 | } 51 | return b[:n], nil 52 | } 53 | } 54 | func (m *EchoRequest) XXX_Merge(src proto.Message) { 55 | xxx_messageInfo_EchoRequest.Merge(m, src) 56 | } 57 | func (m *EchoRequest) XXX_Size() int { 58 | return m.Size() 59 | } 60 | func (m *EchoRequest) XXX_DiscardUnknown() { 61 | xxx_messageInfo_EchoRequest.DiscardUnknown(m) 62 | } 63 | 64 | var xxx_messageInfo_EchoRequest proto.InternalMessageInfo 65 | 66 | func (m *EchoRequest) GetMsg() string { 67 | if m != nil { 68 | return m.Msg 69 | } 70 | return "" 71 | } 72 | 73 | type EchoResponse struct { 74 | Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` 75 | } 76 | 77 | func (m *EchoResponse) Reset() { *m = EchoResponse{} } 78 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) } 79 | func (*EchoResponse) ProtoMessage() {} 80 | func (*EchoResponse) Descriptor() ([]byte, []int) { 81 | return fileDescriptor_08134aea513e0001, []int{1} 82 | } 83 | func (m *EchoResponse) XXX_Unmarshal(b []byte) error { 84 | return m.Unmarshal(b) 85 | } 86 | func (m *EchoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 87 | if deterministic { 88 | return xxx_messageInfo_EchoResponse.Marshal(b, m, deterministic) 89 | } else { 90 | b = b[:cap(b)] 91 | n, err := m.MarshalToSizedBuffer(b) 92 | if err != nil { 93 | return nil, err 94 | } 95 | return b[:n], nil 96 | } 97 | } 98 | func (m *EchoResponse) XXX_Merge(src proto.Message) { 99 | xxx_messageInfo_EchoResponse.Merge(m, src) 100 | } 101 | func (m *EchoResponse) XXX_Size() int { 102 | return m.Size() 103 | } 104 | func (m *EchoResponse) XXX_DiscardUnknown() { 105 | xxx_messageInfo_EchoResponse.DiscardUnknown(m) 106 | } 107 | 108 | var xxx_messageInfo_EchoResponse proto.InternalMessageInfo 109 | 110 | func (m *EchoResponse) GetMsg() string { 111 | if m != nil { 112 | return m.Msg 113 | } 114 | return "" 115 | } 116 | 117 | func init() { 118 | proto.RegisterType((*EchoRequest)(nil), "rpcbench.EchoRequest") 119 | proto.RegisterType((*EchoResponse)(nil), "rpcbench.EchoResponse") 120 | } 121 | 122 | func init() { proto.RegisterFile("echo.proto", fileDescriptor_08134aea513e0001) } 123 | 124 | var fileDescriptor_08134aea513e0001 = []byte{ 125 | // 166 bytes of a gzipped FileDescriptorProto 126 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8, 127 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x2a, 0x48, 0x4e, 0x4a, 0xcd, 0x4b, 0xce, 128 | 0x50, 0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 129 | 0x12, 0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 130 | 0x14, 0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x18, 0x35, 0x31, 131 | 0x72, 0xb1, 0x80, 0x94, 0x08, 0x99, 0x43, 0x69, 0x51, 0x3d, 0x98, 0xf1, 0x7a, 0x48, 0x66, 0x4b, 132 | 0x89, 0xa1, 0x0b, 0x43, 0x4c, 0x54, 0x62, 0x10, 0x72, 0xe4, 0xe2, 0x0a, 0x2e, 0x29, 0x4a, 0x4d, 133 | 0xcc, 0x25, 0x4b, 0xbb, 0x06, 0xa3, 0x01, 0xa3, 0x93, 0xc4, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 134 | 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 135 | 0x1e, 0xcb, 0x31, 0x24, 0xb1, 0x81, 0xbd, 0x6c, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x99, 0xdf, 136 | 0x42, 0x78, 0x00, 0x01, 0x00, 0x00, 137 | } 138 | 139 | // Reference imports to suppress errors if they are not otherwise used. 140 | var _ context.Context 141 | var _ grpc.ClientConn 142 | 143 | // This is a compile-time assertion to ensure that this generated file 144 | // is compatible with the grpc package it is being compiled against. 145 | const _ = grpc.SupportPackageIsVersion4 146 | 147 | // EchoClient is the client API for Echo service. 148 | // 149 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 150 | type EchoClient interface { 151 | Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) 152 | StreamEcho(ctx context.Context, opts ...grpc.CallOption) (Echo_StreamEchoClient, error) 153 | } 154 | 155 | type echoClient struct { 156 | cc *grpc.ClientConn 157 | } 158 | 159 | func NewEchoClient(cc *grpc.ClientConn) EchoClient { 160 | return &echoClient{cc} 161 | } 162 | 163 | func (c *echoClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { 164 | out := new(EchoResponse) 165 | err := c.cc.Invoke(ctx, "/rpcbench.Echo/Echo", in, out, opts...) 166 | if err != nil { 167 | return nil, err 168 | } 169 | return out, nil 170 | } 171 | 172 | func (c *echoClient) StreamEcho(ctx context.Context, opts ...grpc.CallOption) (Echo_StreamEchoClient, error) { 173 | stream, err := c.cc.NewStream(ctx, &_Echo_serviceDesc.Streams[0], "/rpcbench.Echo/StreamEcho", opts...) 174 | if err != nil { 175 | return nil, err 176 | } 177 | x := &echoStreamEchoClient{stream} 178 | return x, nil 179 | } 180 | 181 | type Echo_StreamEchoClient interface { 182 | Send(*EchoRequest) error 183 | Recv() (*EchoResponse, error) 184 | grpc.ClientStream 185 | } 186 | 187 | type echoStreamEchoClient struct { 188 | grpc.ClientStream 189 | } 190 | 191 | func (x *echoStreamEchoClient) Send(m *EchoRequest) error { 192 | return x.ClientStream.SendMsg(m) 193 | } 194 | 195 | func (x *echoStreamEchoClient) Recv() (*EchoResponse, error) { 196 | m := new(EchoResponse) 197 | if err := x.ClientStream.RecvMsg(m); err != nil { 198 | return nil, err 199 | } 200 | return m, nil 201 | } 202 | 203 | // EchoServer is the server API for Echo service. 204 | type EchoServer interface { 205 | Echo(context.Context, *EchoRequest) (*EchoResponse, error) 206 | StreamEcho(Echo_StreamEchoServer) error 207 | } 208 | 209 | // UnimplementedEchoServer can be embedded to have forward compatible implementations. 210 | type UnimplementedEchoServer struct { 211 | } 212 | 213 | func (*UnimplementedEchoServer) Echo(ctx context.Context, req *EchoRequest) (*EchoResponse, error) { 214 | return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") 215 | } 216 | func (*UnimplementedEchoServer) StreamEcho(srv Echo_StreamEchoServer) error { 217 | return status.Errorf(codes.Unimplemented, "method StreamEcho not implemented") 218 | } 219 | 220 | func RegisterEchoServer(s *grpc.Server, srv EchoServer) { 221 | s.RegisterService(&_Echo_serviceDesc, srv) 222 | } 223 | 224 | func _Echo_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 225 | in := new(EchoRequest) 226 | if err := dec(in); err != nil { 227 | return nil, err 228 | } 229 | if interceptor == nil { 230 | return srv.(EchoServer).Echo(ctx, in) 231 | } 232 | info := &grpc.UnaryServerInfo{ 233 | Server: srv, 234 | FullMethod: "/rpcbench.Echo/Echo", 235 | } 236 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 237 | return srv.(EchoServer).Echo(ctx, req.(*EchoRequest)) 238 | } 239 | return interceptor(ctx, in, info, handler) 240 | } 241 | 242 | func _Echo_StreamEcho_Handler(srv interface{}, stream grpc.ServerStream) error { 243 | return srv.(EchoServer).StreamEcho(&echoStreamEchoServer{stream}) 244 | } 245 | 246 | type Echo_StreamEchoServer interface { 247 | Send(*EchoResponse) error 248 | Recv() (*EchoRequest, error) 249 | grpc.ServerStream 250 | } 251 | 252 | type echoStreamEchoServer struct { 253 | grpc.ServerStream 254 | } 255 | 256 | func (x *echoStreamEchoServer) Send(m *EchoResponse) error { 257 | return x.ServerStream.SendMsg(m) 258 | } 259 | 260 | func (x *echoStreamEchoServer) Recv() (*EchoRequest, error) { 261 | m := new(EchoRequest) 262 | if err := x.ServerStream.RecvMsg(m); err != nil { 263 | return nil, err 264 | } 265 | return m, nil 266 | } 267 | 268 | var _Echo_serviceDesc = grpc.ServiceDesc{ 269 | ServiceName: "rpcbench.Echo", 270 | HandlerType: (*EchoServer)(nil), 271 | Methods: []grpc.MethodDesc{ 272 | { 273 | MethodName: "Echo", 274 | Handler: _Echo_Echo_Handler, 275 | }, 276 | }, 277 | Streams: []grpc.StreamDesc{ 278 | { 279 | StreamName: "StreamEcho", 280 | Handler: _Echo_StreamEcho_Handler, 281 | ServerStreams: true, 282 | ClientStreams: true, 283 | }, 284 | }, 285 | Metadata: "echo.proto", 286 | } 287 | 288 | func (m *EchoRequest) Marshal() (dAtA []byte, err error) { 289 | size := m.Size() 290 | dAtA = make([]byte, size) 291 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 292 | if err != nil { 293 | return nil, err 294 | } 295 | return dAtA[:n], nil 296 | } 297 | 298 | func (m *EchoRequest) MarshalTo(dAtA []byte) (int, error) { 299 | size := m.Size() 300 | return m.MarshalToSizedBuffer(dAtA[:size]) 301 | } 302 | 303 | func (m *EchoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { 304 | i := len(dAtA) 305 | _ = i 306 | var l int 307 | _ = l 308 | if len(m.Msg) > 0 { 309 | i -= len(m.Msg) 310 | copy(dAtA[i:], m.Msg) 311 | i = encodeVarintEcho(dAtA, i, uint64(len(m.Msg))) 312 | i-- 313 | dAtA[i] = 0xa 314 | } 315 | return len(dAtA) - i, nil 316 | } 317 | 318 | func (m *EchoResponse) Marshal() (dAtA []byte, err error) { 319 | size := m.Size() 320 | dAtA = make([]byte, size) 321 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 322 | if err != nil { 323 | return nil, err 324 | } 325 | return dAtA[:n], nil 326 | } 327 | 328 | func (m *EchoResponse) MarshalTo(dAtA []byte) (int, error) { 329 | size := m.Size() 330 | return m.MarshalToSizedBuffer(dAtA[:size]) 331 | } 332 | 333 | func (m *EchoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { 334 | i := len(dAtA) 335 | _ = i 336 | var l int 337 | _ = l 338 | if len(m.Msg) > 0 { 339 | i -= len(m.Msg) 340 | copy(dAtA[i:], m.Msg) 341 | i = encodeVarintEcho(dAtA, i, uint64(len(m.Msg))) 342 | i-- 343 | dAtA[i] = 0xa 344 | } 345 | return len(dAtA) - i, nil 346 | } 347 | 348 | func encodeVarintEcho(dAtA []byte, offset int, v uint64) int { 349 | offset -= sovEcho(v) 350 | base := offset 351 | for v >= 1<<7 { 352 | dAtA[offset] = uint8(v&0x7f | 0x80) 353 | v >>= 7 354 | offset++ 355 | } 356 | dAtA[offset] = uint8(v) 357 | return base 358 | } 359 | func (m *EchoRequest) Size() (n int) { 360 | if m == nil { 361 | return 0 362 | } 363 | var l int 364 | _ = l 365 | l = len(m.Msg) 366 | if l > 0 { 367 | n += 1 + l + sovEcho(uint64(l)) 368 | } 369 | return n 370 | } 371 | 372 | func (m *EchoResponse) Size() (n int) { 373 | if m == nil { 374 | return 0 375 | } 376 | var l int 377 | _ = l 378 | l = len(m.Msg) 379 | if l > 0 { 380 | n += 1 + l + sovEcho(uint64(l)) 381 | } 382 | return n 383 | } 384 | 385 | func sovEcho(x uint64) (n int) { 386 | return (math_bits.Len64(x|1) + 6) / 7 387 | } 388 | func sozEcho(x uint64) (n int) { 389 | return sovEcho(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 390 | } 391 | func (m *EchoRequest) Unmarshal(dAtA []byte) error { 392 | l := len(dAtA) 393 | iNdEx := 0 394 | for iNdEx < l { 395 | preIndex := iNdEx 396 | var wire uint64 397 | for shift := uint(0); ; shift += 7 { 398 | if shift >= 64 { 399 | return ErrIntOverflowEcho 400 | } 401 | if iNdEx >= l { 402 | return io.ErrUnexpectedEOF 403 | } 404 | b := dAtA[iNdEx] 405 | iNdEx++ 406 | wire |= uint64(b&0x7F) << shift 407 | if b < 0x80 { 408 | break 409 | } 410 | } 411 | fieldNum := int32(wire >> 3) 412 | wireType := int(wire & 0x7) 413 | if wireType == 4 { 414 | return fmt.Errorf("proto: EchoRequest: wiretype end group for non-group") 415 | } 416 | if fieldNum <= 0 { 417 | return fmt.Errorf("proto: EchoRequest: illegal tag %d (wire type %d)", fieldNum, wire) 418 | } 419 | switch fieldNum { 420 | case 1: 421 | if wireType != 2 { 422 | return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType) 423 | } 424 | var stringLen uint64 425 | for shift := uint(0); ; shift += 7 { 426 | if shift >= 64 { 427 | return ErrIntOverflowEcho 428 | } 429 | if iNdEx >= l { 430 | return io.ErrUnexpectedEOF 431 | } 432 | b := dAtA[iNdEx] 433 | iNdEx++ 434 | stringLen |= uint64(b&0x7F) << shift 435 | if b < 0x80 { 436 | break 437 | } 438 | } 439 | intStringLen := int(stringLen) 440 | if intStringLen < 0 { 441 | return ErrInvalidLengthEcho 442 | } 443 | postIndex := iNdEx + intStringLen 444 | if postIndex < 0 { 445 | return ErrInvalidLengthEcho 446 | } 447 | if postIndex > l { 448 | return io.ErrUnexpectedEOF 449 | } 450 | m.Msg = string(dAtA[iNdEx:postIndex]) 451 | iNdEx = postIndex 452 | default: 453 | iNdEx = preIndex 454 | skippy, err := skipEcho(dAtA[iNdEx:]) 455 | if err != nil { 456 | return err 457 | } 458 | if skippy < 0 { 459 | return ErrInvalidLengthEcho 460 | } 461 | if (iNdEx + skippy) < 0 { 462 | return ErrInvalidLengthEcho 463 | } 464 | if (iNdEx + skippy) > l { 465 | return io.ErrUnexpectedEOF 466 | } 467 | iNdEx += skippy 468 | } 469 | } 470 | 471 | if iNdEx > l { 472 | return io.ErrUnexpectedEOF 473 | } 474 | return nil 475 | } 476 | func (m *EchoResponse) Unmarshal(dAtA []byte) error { 477 | l := len(dAtA) 478 | iNdEx := 0 479 | for iNdEx < l { 480 | preIndex := iNdEx 481 | var wire uint64 482 | for shift := uint(0); ; shift += 7 { 483 | if shift >= 64 { 484 | return ErrIntOverflowEcho 485 | } 486 | if iNdEx >= l { 487 | return io.ErrUnexpectedEOF 488 | } 489 | b := dAtA[iNdEx] 490 | iNdEx++ 491 | wire |= uint64(b&0x7F) << shift 492 | if b < 0x80 { 493 | break 494 | } 495 | } 496 | fieldNum := int32(wire >> 3) 497 | wireType := int(wire & 0x7) 498 | if wireType == 4 { 499 | return fmt.Errorf("proto: EchoResponse: wiretype end group for non-group") 500 | } 501 | if fieldNum <= 0 { 502 | return fmt.Errorf("proto: EchoResponse: illegal tag %d (wire type %d)", fieldNum, wire) 503 | } 504 | switch fieldNum { 505 | case 1: 506 | if wireType != 2 { 507 | return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType) 508 | } 509 | var stringLen uint64 510 | for shift := uint(0); ; shift += 7 { 511 | if shift >= 64 { 512 | return ErrIntOverflowEcho 513 | } 514 | if iNdEx >= l { 515 | return io.ErrUnexpectedEOF 516 | } 517 | b := dAtA[iNdEx] 518 | iNdEx++ 519 | stringLen |= uint64(b&0x7F) << shift 520 | if b < 0x80 { 521 | break 522 | } 523 | } 524 | intStringLen := int(stringLen) 525 | if intStringLen < 0 { 526 | return ErrInvalidLengthEcho 527 | } 528 | postIndex := iNdEx + intStringLen 529 | if postIndex < 0 { 530 | return ErrInvalidLengthEcho 531 | } 532 | if postIndex > l { 533 | return io.ErrUnexpectedEOF 534 | } 535 | m.Msg = string(dAtA[iNdEx:postIndex]) 536 | iNdEx = postIndex 537 | default: 538 | iNdEx = preIndex 539 | skippy, err := skipEcho(dAtA[iNdEx:]) 540 | if err != nil { 541 | return err 542 | } 543 | if skippy < 0 { 544 | return ErrInvalidLengthEcho 545 | } 546 | if (iNdEx + skippy) < 0 { 547 | return ErrInvalidLengthEcho 548 | } 549 | if (iNdEx + skippy) > l { 550 | return io.ErrUnexpectedEOF 551 | } 552 | iNdEx += skippy 553 | } 554 | } 555 | 556 | if iNdEx > l { 557 | return io.ErrUnexpectedEOF 558 | } 559 | return nil 560 | } 561 | func skipEcho(dAtA []byte) (n int, err error) { 562 | l := len(dAtA) 563 | iNdEx := 0 564 | depth := 0 565 | for iNdEx < l { 566 | var wire uint64 567 | for shift := uint(0); ; shift += 7 { 568 | if shift >= 64 { 569 | return 0, ErrIntOverflowEcho 570 | } 571 | if iNdEx >= l { 572 | return 0, io.ErrUnexpectedEOF 573 | } 574 | b := dAtA[iNdEx] 575 | iNdEx++ 576 | wire |= (uint64(b) & 0x7F) << shift 577 | if b < 0x80 { 578 | break 579 | } 580 | } 581 | wireType := int(wire & 0x7) 582 | switch wireType { 583 | case 0: 584 | for shift := uint(0); ; shift += 7 { 585 | if shift >= 64 { 586 | return 0, ErrIntOverflowEcho 587 | } 588 | if iNdEx >= l { 589 | return 0, io.ErrUnexpectedEOF 590 | } 591 | iNdEx++ 592 | if dAtA[iNdEx-1] < 0x80 { 593 | break 594 | } 595 | } 596 | case 1: 597 | iNdEx += 8 598 | case 2: 599 | var length int 600 | for shift := uint(0); ; shift += 7 { 601 | if shift >= 64 { 602 | return 0, ErrIntOverflowEcho 603 | } 604 | if iNdEx >= l { 605 | return 0, io.ErrUnexpectedEOF 606 | } 607 | b := dAtA[iNdEx] 608 | iNdEx++ 609 | length |= (int(b) & 0x7F) << shift 610 | if b < 0x80 { 611 | break 612 | } 613 | } 614 | if length < 0 { 615 | return 0, ErrInvalidLengthEcho 616 | } 617 | iNdEx += length 618 | case 3: 619 | depth++ 620 | case 4: 621 | if depth == 0 { 622 | return 0, ErrUnexpectedEndOfGroupEcho 623 | } 624 | depth-- 625 | case 5: 626 | iNdEx += 4 627 | default: 628 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 629 | } 630 | if iNdEx < 0 { 631 | return 0, ErrInvalidLengthEcho 632 | } 633 | if depth == 0 { 634 | return iNdEx, nil 635 | } 636 | } 637 | return 0, io.ErrUnexpectedEOF 638 | } 639 | 640 | var ( 641 | ErrInvalidLengthEcho = fmt.Errorf("proto: negative length found during unmarshaling") 642 | ErrIntOverflowEcho = fmt.Errorf("proto: integer overflow") 643 | ErrUnexpectedEndOfGroupEcho = fmt.Errorf("proto: unexpected end of group") 644 | ) 645 | -------------------------------------------------------------------------------- /echo.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package rpcbench; 8 | 9 | service Echo { 10 | rpc Echo (EchoRequest) returns (EchoResponse) {} 11 | rpc StreamEcho (stream EchoRequest) returns (stream EchoResponse) {} 12 | } 13 | 14 | message EchoRequest { 15 | string msg = 1; 16 | } 17 | 18 | message EchoResponse { 19 | string msg = 1; 20 | } 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cockroachdb/rpc-bench 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gogo/protobuf v1.3.1 7 | github.com/golang/protobuf v1.4.0 // indirect 8 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect 9 | golang.org/x/perf v0.0.0-20200318175901-9c9101da8316 10 | golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect 11 | golang.org/x/text v0.3.2 // indirect 12 | golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290 // indirect 13 | google.golang.org/genproto v0.0.0-20200417142217-fb6d0575620b // indirect 14 | google.golang.org/grpc v1.28.1 15 | honnef.co/go/tools v0.0.1-2020.1.3 16 | ) 17 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 4 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 5 | github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= 6 | github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= 7 | github.com/aclements/go-moremath v0.0.0-20161014184102-0ff62e0875ff/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ= 8 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 9 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 10 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 11 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 12 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 13 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 14 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 15 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 16 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= 17 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 18 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 19 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 20 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 21 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 22 | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= 23 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 24 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 25 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 26 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 27 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 28 | github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= 29 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 30 | github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= 31 | github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= 32 | github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= 33 | github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= 34 | github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= 35 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 36 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 37 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 38 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 39 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 40 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 41 | github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 42 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 43 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 44 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 45 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 46 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 47 | github.com/mattn/go-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 48 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 49 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 50 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 51 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 52 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 53 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 54 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 55 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 56 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 57 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 58 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 59 | golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= 60 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 61 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 62 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 63 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 64 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 65 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 66 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 67 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 68 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 69 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= 70 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 71 | golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 72 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 73 | golang.org/x/perf v0.0.0-20200318175901-9c9101da8316 h1:4kYIkqY0RFzbXzKPeT7sNOlcJK5JY1HSnMBOUlzXlZU= 74 | golang.org/x/perf v0.0.0-20200318175901-9c9101da8316/go.mod h1:FrqOtQDO3iMDVUtw5nNTDFpR1HUCGh00M3kj2wiSzLQ= 75 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 76 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 77 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 78 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 79 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 80 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 81 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 82 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 83 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 84 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 85 | golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= 86 | golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 87 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 88 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 89 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 90 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 91 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 92 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 93 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 94 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 95 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 96 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= 97 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 98 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 99 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 100 | golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290 h1:NXNmtp0ToD36cui5IqWy95LC4Y6vT/4y3RnPxlQPinU= 101 | golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 102 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 103 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 104 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 105 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 106 | google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 107 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 108 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 109 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 110 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 111 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 112 | google.golang.org/genproto v0.0.0-20200417142217-fb6d0575620b h1:/sPqdbf2Q/AnRN3tAvFK2u6uJjWjALyX3FDMCkPBpSw= 113 | google.golang.org/genproto v0.0.0-20200417142217-fb6d0575620b/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 114 | google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 115 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 116 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 117 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 118 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 119 | google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= 120 | google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 121 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 122 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 123 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 124 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 125 | google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= 126 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 127 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 128 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 129 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 130 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs= 131 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 132 | honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= 133 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 134 | -------------------------------------------------------------------------------- /rpc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | // 16 | // Author: Tamir Duberstein (tamird@gmail.com) 17 | 18 | package rpcbench 19 | 20 | import ( 21 | "bytes" 22 | "context" 23 | "crypto/tls" 24 | "fmt" 25 | "io/ioutil" 26 | "math/rand" 27 | "net" 28 | "net/http" 29 | "net/rpc" 30 | "strings" 31 | "sync" 32 | "testing" 33 | 34 | "github.com/gogo/protobuf/proto" 35 | "google.golang.org/grpc" 36 | "google.golang.org/grpc/credentials" 37 | ) 38 | 39 | func init() { 40 | grpc.EnableTracing = false 41 | } 42 | 43 | var clientTLSConfig = &tls.Config{ 44 | InsecureSkipVerify: true, 45 | } 46 | 47 | var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 48 | 49 | func randString(n int) string { 50 | b := make([]rune, n) 51 | for i := range b { 52 | b[i] = letterRunes[rand.Intn(len(letterRunes))] 53 | } 54 | return string(b) 55 | } 56 | 57 | func benchmarkEcho(b *testing.B, size int, accept func(net.Listener, *tls.Config) error, setup func(net.Addr), teardown func(), setupParallel func() func(string) string) { 58 | cert, err := tls.LoadX509KeyPair("server.crt", "server.key") 59 | if err != nil { 60 | b.Fatal(err) 61 | } 62 | 63 | listener, err := net.Listen("tcp", ":0") 64 | if err != nil { 65 | b.Fatal(err) 66 | } 67 | 68 | tlsConfig := &tls.Config{ 69 | Certificates: []tls.Certificate{cert}, 70 | // Enable HTTP/2. 71 | NextProtos: []string{"h2"}, 72 | } 73 | 74 | listener = tls.NewListener(listener, tlsConfig) 75 | 76 | var wg sync.WaitGroup 77 | wg.Add(1) 78 | go func() { 79 | defer wg.Done() 80 | 81 | if err := accept(listener, tlsConfig); err != nil && !strings.HasSuffix(err.Error(), "use of closed network connection") { 82 | b.Error(err) 83 | } 84 | }() 85 | defer wg.Wait() 86 | 87 | defer func() { 88 | if err := listener.Close(); err != nil { 89 | b.Fatal(err) 90 | } 91 | }() 92 | 93 | if setup != nil { 94 | setup(listener.Addr()) 95 | } 96 | 97 | echoMsg := randString(size) 98 | 99 | b.SetBytes(2 * int64(len(echoMsg))) 100 | b.ResetTimer() 101 | 102 | b.RunParallel(func(pb *testing.PB) { 103 | runRequest := setupParallel() 104 | 105 | for pb.Next() { 106 | if a, e := runRequest(echoMsg), echoMsg; a != e { 107 | b.Fatalf("expected:\n%q\ngot:\n%q", e, a) 108 | } 109 | } 110 | }) 111 | 112 | b.StopTimer() 113 | 114 | if teardown != nil { 115 | teardown() 116 | } 117 | } 118 | 119 | // grpc 120 | 121 | type echoServer struct{} 122 | 123 | func (e *echoServer) Echo(ctx context.Context, req *EchoRequest) (*EchoResponse, error) { 124 | return &EchoResponse{Msg: req.Msg}, nil 125 | } 126 | 127 | func (e *echoServer) StreamEcho(s Echo_StreamEchoServer) error { 128 | for { 129 | if s.Context().Err() != nil { 130 | return nil 131 | } 132 | req, err := s.Recv() 133 | if err != nil { 134 | return err 135 | } 136 | if err := s.Send(&EchoResponse{Msg: req.Msg}); err != nil { 137 | return err 138 | } 139 | } 140 | } 141 | 142 | func benchmarkEchoGRPC(b *testing.B, listenAndServeFn func(net.Listener, *tls.Config) error, size int) { 143 | var conn *grpc.ClientConn 144 | var client EchoClient 145 | benchmarkEcho(b, size, listenAndServeFn, 146 | func(addr net.Addr) { 147 | var err error 148 | conn, err = grpc.Dial(addr.String(), grpc.WithTransportCredentials(credentials.NewTLS(clientTLSConfig)), grpc.WithBlock()) 149 | if err != nil { 150 | b.Fatal(err) 151 | } 152 | client = NewEchoClient(conn) 153 | }, 154 | func() { 155 | if err := conn.Close(); err != nil { 156 | b.Fatal(err) 157 | } 158 | }, 159 | func() func(string) string { 160 | return func(echoMsg string) string { 161 | resp, err := client.Echo(context.Background(), &EchoRequest{Msg: echoMsg}) 162 | if err != nil { 163 | b.Fatal(err) 164 | } 165 | return resp.Msg 166 | } 167 | }, 168 | ) 169 | } 170 | 171 | func benchmarkEchoStreamGRPC(b *testing.B, listenAndServeFn func(net.Listener, *tls.Config) error, size int) { 172 | var conn *grpc.ClientConn 173 | var client EchoClient 174 | benchmarkEcho(b, size, listenAndServeFn, 175 | func(addr net.Addr) { 176 | var err error 177 | conn, err = grpc.Dial(addr.String(), grpc.WithTransportCredentials(credentials.NewTLS(clientTLSConfig)), grpc.WithBlock()) 178 | if err != nil { 179 | b.Fatal(err) 180 | } 181 | client = NewEchoClient(conn) 182 | }, 183 | func() { 184 | if err := conn.Close(); err != nil { 185 | b.Fatal(err) 186 | } 187 | }, 188 | func() func(string) string { 189 | stream, err := client.StreamEcho(context.Background()) 190 | if err != nil { 191 | b.Fatal(err) 192 | } 193 | return func(echoMsg string) string { 194 | if err := stream.Send(&EchoRequest{Msg: echoMsg}); err != nil { 195 | b.Fatal(err) 196 | } 197 | resp, err := stream.Recv() 198 | if err != nil { 199 | b.Fatal(err) 200 | } 201 | return resp.Msg 202 | } 203 | }, 204 | ) 205 | } 206 | 207 | // Serve 208 | 209 | func listenAndServeGRPCServe(listener net.Listener, _ *tls.Config) error { 210 | grpcServer := grpc.NewServer() 211 | RegisterEchoServer(grpcServer, new(echoServer)) 212 | return grpcServer.Serve(listener) 213 | } 214 | 215 | func BenchmarkGRPCServe_1K(b *testing.B) { 216 | benchmarkEchoGRPC(b, listenAndServeGRPCServe, 1<<10) 217 | } 218 | 219 | func BenchmarkGRPCServe_64K(b *testing.B) { 220 | benchmarkEchoGRPC(b, listenAndServeGRPCServe, 64<<10) 221 | } 222 | 223 | func BenchmarkGRPCServe_Stream_1K(b *testing.B) { 224 | benchmarkEchoStreamGRPC(b, listenAndServeGRPCServe, 1<<10) 225 | } 226 | 227 | func BenchmarkGRPCServe_Stream_64k(b *testing.B) { 228 | benchmarkEchoStreamGRPC(b, listenAndServeGRPCServe, 64<<10) 229 | } 230 | 231 | // ServeHTTP 232 | 233 | func listenAndServeGRPCServeHTTP(listener net.Listener, tlsConfig *tls.Config) error { 234 | grpcServer := grpc.NewServer() 235 | RegisterEchoServer(grpcServer, new(echoServer)) 236 | srv := http.Server{ 237 | TLSConfig: tlsConfig, 238 | Handler: grpcServer, 239 | } 240 | 241 | return srv.Serve(listener) 242 | } 243 | 244 | func BenchmarkGRPCServeHTTP_1K(b *testing.B) { 245 | benchmarkEchoGRPC(b, listenAndServeGRPCServeHTTP, 1<<10) 246 | } 247 | 248 | func BenchmarkGRPCServeHTTP_64K(b *testing.B) { 249 | benchmarkEchoGRPC(b, listenAndServeGRPCServeHTTP, 64<<10) 250 | } 251 | 252 | func BenchmarkGRPCServeHTTP_Stream_1K(b *testing.B) { 253 | benchmarkEchoStreamGRPC(b, listenAndServeGRPCServeHTTP, 1<<10) 254 | } 255 | 256 | func BenchmarkGRPCServeHTTP_Stream_64k(b *testing.B) { 257 | benchmarkEchoStreamGRPC(b, listenAndServeGRPCServeHTTP, 64<<10) 258 | } 259 | 260 | // gob-rpc 261 | 262 | type Echo struct{} 263 | 264 | func (t *Echo) Echo(args *EchoRequest, reply *EchoResponse) error { 265 | reply.Msg = args.Msg 266 | return nil 267 | } 268 | 269 | func listenAndServeGobRPC(listener net.Listener, _ *tls.Config) error { 270 | rpcServer := rpc.NewServer() 271 | if err := rpcServer.Register(new(Echo)); err != nil { 272 | return err 273 | } 274 | for { 275 | conn, err := listener.Accept() 276 | if err != nil { 277 | return err 278 | } 279 | go rpcServer.ServeConn(conn) 280 | } 281 | } 282 | 283 | func benchmarkEchoGobRPC(b *testing.B, size int) { 284 | var client *rpc.Client 285 | benchmarkEcho(b, size, listenAndServeGobRPC, 286 | func(addr net.Addr) { 287 | var err error 288 | conn, err := tls.Dial(addr.Network(), addr.String(), clientTLSConfig) 289 | if err != nil { 290 | b.Fatal(err) 291 | } 292 | client = rpc.NewClient(conn) 293 | if err != nil { 294 | b.Fatal(err) 295 | } 296 | }, 297 | func() { 298 | if err := client.Close(); err != nil { 299 | b.Fatal(err) 300 | } 301 | }, 302 | func() func(string) string { 303 | return func(echoMsg string) string { 304 | args := EchoRequest{Msg: echoMsg} 305 | var reply EchoResponse 306 | if err := client.Call("Echo.Echo", &args, &reply); err != nil { 307 | b.Fatal(err) 308 | } 309 | return reply.Msg 310 | } 311 | }, 312 | ) 313 | } 314 | 315 | func BenchmarkGobRPC_1K(b *testing.B) { 316 | benchmarkEchoGobRPC(b, 1<<10) 317 | } 318 | 319 | func BenchmarkGobRPC_64K(b *testing.B) { 320 | benchmarkEchoGobRPC(b, 64<<10) 321 | } 322 | 323 | // proto-rpc 324 | 325 | func listenAndServeProtoRPC(listener net.Listener, _ *tls.Config) error { 326 | rpcServer := rpc.NewServer() 327 | if err := rpcServer.Register(new(Echo)); err != nil { 328 | return err 329 | } 330 | for { 331 | conn, err := listener.Accept() 332 | if err != nil { 333 | return err 334 | } 335 | 336 | go ServeConn(rpcServer, conn) 337 | } 338 | } 339 | 340 | func benchmarkEchoProtoRPC(b *testing.B, size int) { 341 | var client *rpc.Client 342 | benchmarkEcho(b, size, listenAndServeProtoRPC, 343 | func(addr net.Addr) { 344 | conn, err := tls.Dial(addr.Network(), addr.String(), clientTLSConfig) 345 | if err != nil { 346 | b.Fatal(err) 347 | } 348 | client = NewClient(conn) 349 | }, 350 | func() { 351 | if err := client.Close(); err != nil { 352 | b.Fatal(err) 353 | } 354 | }, 355 | func() func(string) string { 356 | return func(echoMsg string) string { 357 | args := EchoRequest{Msg: echoMsg} 358 | var reply EchoResponse 359 | if err := client.Call("Echo.Echo", &args, &reply); err != nil { 360 | b.Fatal(err) 361 | } 362 | return reply.Msg 363 | } 364 | }, 365 | ) 366 | } 367 | 368 | func BenchmarkProtoRPC_1K(b *testing.B) { 369 | benchmarkEchoProtoRPC(b, 1<<10) 370 | } 371 | 372 | func BenchmarkProtoRPC_64K(b *testing.B) { 373 | benchmarkEchoProtoRPC(b, 64<<10) 374 | } 375 | 376 | // proto-http 377 | 378 | const ( 379 | contentType = "Content-Type" 380 | xProtobuf = "application/x-protobuf" 381 | ) 382 | 383 | func listenAndServeProtoHTTP(listener net.Listener, tlsConfig *tls.Config) error { 384 | srv := http.Server{ 385 | TLSConfig: tlsConfig, 386 | Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 387 | reqBody, err := ioutil.ReadAll(r.Body) 388 | if err != nil { 389 | http.Error(w, err.Error(), http.StatusInternalServerError) 390 | return 391 | } 392 | if err := r.Body.Close(); err != nil { 393 | http.Error(w, err.Error(), http.StatusInternalServerError) 394 | return 395 | } 396 | var args EchoRequest 397 | if err := proto.Unmarshal(reqBody, &args); err != nil { 398 | http.Error(w, err.Error(), http.StatusBadRequest) 399 | return 400 | } 401 | reply := EchoResponse(args) 402 | respBody, err := proto.Marshal(&reply) 403 | if err != nil { 404 | http.Error(w, err.Error(), http.StatusInternalServerError) 405 | return 406 | } 407 | w.Header().Set(contentType, xProtobuf) 408 | w.Write(respBody) 409 | }), 410 | } 411 | 412 | return srv.Serve(listener) 413 | } 414 | 415 | func benchmarkEchoProtoHTTP(b *testing.B, size int, accept func(net.Listener, *tls.Config) error, roundTripper http.RoundTripper) { 416 | var url string 417 | benchmarkEcho(b, size, accept, 418 | func(addr net.Addr) { 419 | url = fmt.Sprintf("https://%s", addr) 420 | }, 421 | nil, 422 | func() func(string) string { 423 | return func(echoMsg string) string { 424 | args := EchoRequest{Msg: echoMsg} 425 | reqBody, err := proto.Marshal(&args) 426 | if err != nil { 427 | b.Fatal(err) 428 | } 429 | req, err := http.NewRequest("POST", url, bytes.NewReader(reqBody)) 430 | if err != nil { 431 | b.Fatal(err) 432 | } 433 | req.Header.Set("Content-Type", xProtobuf) 434 | resp, err := roundTripper.RoundTrip(req) 435 | if err != nil { 436 | b.Fatal(err) 437 | } 438 | respBody, err := ioutil.ReadAll(resp.Body) 439 | if err != nil { 440 | b.Fatal(err) 441 | } 442 | if err := resp.Body.Close(); err != nil { 443 | b.Fatal(err) 444 | } 445 | var reply EchoResponse 446 | if err := proto.Unmarshal(respBody, &reply); err != nil { 447 | b.Fatal(err) 448 | } 449 | return reply.Msg 450 | } 451 | }, 452 | ) 453 | } 454 | 455 | func benchmarkEchoProtoHTTP1(b *testing.B, size int) { 456 | benchmarkEchoProtoHTTP(b, size, listenAndServeProtoHTTP, &http.Transport{ 457 | TLSClientConfig: clientTLSConfig, 458 | // Disable HTTP/2. 459 | TLSNextProto: make(map[string]func(string, *tls.Conn) http.RoundTripper), 460 | }) 461 | } 462 | 463 | func BenchmarkProtoHTTP1_1K(b *testing.B) { 464 | benchmarkEchoProtoHTTP1(b, 1<<10) 465 | } 466 | 467 | func BenchmarkProtoHTTP1_64K(b *testing.B) { 468 | benchmarkEchoProtoHTTP1(b, 64<<10) 469 | } 470 | 471 | func benchmarkEchoProtoHTTP2(b *testing.B, size int) { 472 | benchmarkEchoProtoHTTP(b, size, listenAndServeProtoHTTP, &http.Transport{ 473 | TLSClientConfig: clientTLSConfig, 474 | ForceAttemptHTTP2: true, 475 | }) 476 | } 477 | 478 | func BenchmarkProtoHTTP2_1K(b *testing.B) { 479 | benchmarkEchoProtoHTTP2(b, 1<<10) 480 | } 481 | 482 | func BenchmarkProtoHTTP2_64K(b *testing.B) { 483 | benchmarkEchoProtoHTTP2(b, 64<<10) 484 | } 485 | -------------------------------------------------------------------------------- /server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDPjCCAiYCCQDizia/MoUFnDANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoT 4 | C0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhvc3QxHTAbBgkqhkiG9w0BCQEW 5 | DmJyYWRAZGFuZ2EuY29tMB4XDTE0MDcxNTIwNTAyN1oXDTE1MTEyNzIwNTAyN1ow 6 | RzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJTRjEeMBwGA1UE 7 | ChMVYnJhZGZpdHogaHR0cDIgc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 8 | MIIBCgKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDifx2l 9 | gZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1LmJ4c2 10 | dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nefb3HL 11 | A7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55mjws 12 | /vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/fz88 13 | F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB 14 | AQC0zL+n/YpRZOdulSu9tS8FxrstXqGWoxfe+vIUgqfMZ5+0MkjJ/vW0FqlLDl2R 15 | rn4XaR3e7FmWkwdDVbq/UB6lPmoAaFkCgh9/5oapMaclNVNnfF3fjCJfRr+qj/iD 16 | EmJStTIN0ZuUjAlpiACmfnpEU55PafT5Zx+i1yE4FGjw8bJpFoyD4Hnm54nGjX19 17 | KeCuvcYFUPnBm3lcL0FalF2AjqV02WTHYNQk7YF/oeO7NKBoEgvGvKG3x+xaOeBI 18 | dwvdq175ZsGul30h+QjrRlXhH/twcuaT3GSdoysDl9cCYE8f1Mk8PD6gan3uBCJU 19 | 90p6/CbU71bGbfpM2PHot2fm 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | // 16 | // Author: Peter Mattis (peter@cockroachlabs.com) 17 | 18 | // Copyright 2013 . All rights reserved. 19 | // Use of this source code is governed by a BSD-style 20 | // license that can be found in the LICENSE file. 21 | 22 | package rpcbench 23 | 24 | import ( 25 | "bufio" 26 | "bytes" 27 | "fmt" 28 | "io" 29 | "net/rpc" 30 | 31 | "github.com/gogo/protobuf/proto" 32 | ) 33 | 34 | type serverCodec struct { 35 | baseConn 36 | 37 | methods []string 38 | 39 | // temporary work space 40 | respBodyBuf bytes.Buffer 41 | respHeaderBuf bytes.Buffer 42 | respHeader ResponseHeader 43 | reqHeader RequestHeader 44 | } 45 | 46 | // NewServerCodec returns a serverCodec that communicates with the ClientCodec 47 | // on the other end of the given conn. 48 | func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec { 49 | return &serverCodec{ 50 | baseConn: baseConn{ 51 | r: bufio.NewReader(conn), 52 | w: bufio.NewWriter(conn), 53 | c: conn, 54 | }, 55 | } 56 | } 57 | 58 | func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error { 59 | err := c.readRequestHeader(c.r, &c.reqHeader) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | r.Seq = c.reqHeader.Id 65 | if len(c.reqHeader.Method) == 0 { 66 | if int(c.reqHeader.MethodId) >= len(c.methods) { 67 | return fmt.Errorf("unexpected method-id: %d >= %d", 68 | c.reqHeader.MethodId, len(c.methods)) 69 | } 70 | r.ServiceMethod = c.methods[c.reqHeader.MethodId] 71 | } else if int(c.reqHeader.MethodId) > len(c.methods) { 72 | return fmt.Errorf("unexpected method-id: %d > %d", 73 | c.reqHeader.MethodId, len(c.methods)) 74 | } else if int(c.reqHeader.MethodId) == len(c.methods) { 75 | c.methods = append(c.methods, c.reqHeader.Method) 76 | r.ServiceMethod = c.reqHeader.Method 77 | } 78 | return nil 79 | } 80 | 81 | func (c *serverCodec) ReadRequestBody(x interface{}) error { 82 | if x == nil { 83 | return nil 84 | } 85 | request, ok := x.(proto.Message) 86 | if !ok { 87 | return fmt.Errorf( 88 | "protorpc.ServerCodec.ReadRequestBody: %T does not implement proto.Message", 89 | x, 90 | ) 91 | } 92 | 93 | err := c.readRequestBody(c.r, &c.reqHeader, request) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | c.reqHeader.Reset() 99 | return nil 100 | } 101 | 102 | func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error { 103 | var response proto.Message 104 | if x != nil { 105 | var ok bool 106 | if response, ok = x.(proto.Message); !ok { 107 | if _, ok = x.(struct{}); !ok { 108 | return fmt.Errorf( 109 | "protorpc.ServerCodec.WriteResponse: %T does not implement proto.Message", 110 | x, 111 | ) 112 | } 113 | } 114 | } 115 | 116 | if err := c.writeResponse(r, response); err != nil { 117 | return err 118 | } 119 | return c.w.Flush() 120 | } 121 | 122 | func (c *serverCodec) writeResponse(r *rpc.Response, response proto.Message) error { 123 | // clear response if error 124 | if r.Error != "" { 125 | response = nil 126 | } 127 | 128 | // marshal response 129 | var pbResponse []byte 130 | if response != nil { 131 | var err error 132 | pbResponse, err = marshal(&c.respBodyBuf, response) 133 | if err != nil { 134 | return err 135 | } 136 | } 137 | 138 | // generate header 139 | header := &c.respHeader 140 | *header = ResponseHeader{ 141 | Id: r.Seq, 142 | // The net/rpc interface asks for the Response.ServiceMethod to be 143 | // returned from the server, but it is never used. 144 | // 145 | // Method: r.ServiceMethod, 146 | Error: r.Error, 147 | Compression: compressionType, 148 | UncompressedSize: uint32(len(pbResponse)), 149 | } 150 | 151 | // marshal header 152 | pbHeader, err := marshal(&c.respHeaderBuf, header) 153 | if err != nil { 154 | return err 155 | } 156 | 157 | // send header (more) 158 | if err := c.sendFrame(pbHeader); err != nil { 159 | return err 160 | } 161 | 162 | // send body (end) 163 | // if compressionType == CompressionType_SNAPPY { 164 | // return snappyEncode(pbResponse, c.sendFrame) 165 | // } else if compressionType == CompressionType_LZ4 { 166 | // return lz4Encode(pbResponse, c.sendFrame) 167 | // } 168 | return c.sendFrame(pbResponse) 169 | } 170 | 171 | func (c *serverCodec) readRequestHeader(r *bufio.Reader, header *RequestHeader) error { 172 | return c.recvProto(header, 0, protoUnmarshal) 173 | } 174 | 175 | func (c *serverCodec) readRequestBody(r *bufio.Reader, header *RequestHeader, 176 | request proto.Message) error { 177 | return c.recvProto(request, header.UncompressedSize, decompressors[header.Compression]) 178 | } 179 | 180 | // ServeConn runs the Protobuf-RPC server on a single connection. 181 | // ServeConn blocks, serving the connection until the client hangs up. 182 | // The caller typically invokes ServeConn in a go statement. 183 | func ServeConn(server *rpc.Server, conn io.ReadWriteCloser) { 184 | server.ServeCodec(NewServerCodec(conn)) 185 | } 186 | 187 | type marshalTo interface { 188 | Size() int 189 | MarshalTo([]byte) (int, error) 190 | } 191 | 192 | func marshal(buf *bytes.Buffer, m proto.Message) ([]byte, error) { 193 | if m == nil { 194 | return nil, nil 195 | } 196 | if mt, ok := m.(marshalTo); ok { 197 | buf.Reset() 198 | size := mt.Size() 199 | buf.Grow(size) 200 | b := buf.Bytes()[:size] 201 | n, err := mt.MarshalTo(b) 202 | return b[:n], err 203 | } 204 | return proto.Marshal(m) 205 | } 206 | -------------------------------------------------------------------------------- /server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDi 3 | fx2lgZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1Lm 4 | J4c2dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nef 5 | b3HLA7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55 6 | mjws/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/ 7 | fz88F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABAoIBADQ2spUwbY+bcz4p 8 | 3M66ECrNQTBggP40gYl2XyHxGGOu2xhZ94f9ELf1hjRWU2DUKWco1rJcdZClV6q3 9 | qwmXvcM2Q/SMS8JW0ImkNVl/0/NqPxGatEnj8zY30d/L8hGFb0orzFu/XYA5gCP4 10 | NbN2WrXgk3ZLeqwcNxHHtSiJWGJ/fPyeDWAu/apy75u9Xf2GlzBZmV6HYD9EfK80 11 | LTlI60f5FO487CrJnboL7ovPJrIHn+k05xRQqwma4orpz932rTXnTjs9Lg6KtbQN 12 | a7PrqfAntIISgr11a66Mng3IYH1lYqJsWJJwX/xHT4WLEy0EH4/0+PfYemJekz2+ 13 | Co62drECgYEA6O9zVJZXrLSDsIi54cfxA7nEZWm5CAtkYWeAHa4EJ+IlZ7gIf9sL 14 | W8oFcEfFGpvwVqWZ+AsQ70dsjXAv3zXaG0tmg9FtqWp7pzRSMPidifZcQwWkKeTO 15 | gJnFmnVyed8h6GfjTEu4gxo1/S5U0V+mYSha01z5NTnN6ltKx1Or3b0CgYEAxRgm 16 | S30nZxnyg/V7ys61AZhst1DG2tkZXEMcA7dYhabMoXPJAP/EfhlWwpWYYUs/u0gS 17 | Wwmf5IivX5TlYScgmkvb/NYz0u4ZmOXkLTnLPtdKKFXhjXJcHjUP67jYmOxNlJLp 18 | V4vLRnFxTpffAV+OszzRxsXX6fvruwZBANYJeXUCgYBVouLFsFgfWGYp2rpr9XP4 19 | KK25kvrBqF6JKOIDB1zjxNJ3pUMKrl8oqccCFoCyXa4oTM2kUX0yWxHfleUjrMq4 20 | yimwQKiOZmV7fVLSSjSw6e/VfBd0h3gb82ygcplZkN0IclkwTY5SNKqwn/3y07V5 21 | drqdhkrgdJXtmQ6O5YYECQKBgATERcDToQ1USlI4sKrB/wyv1AlG8dg/IebiVJ4e 22 | ZAyvcQmClFzq0qS+FiQUnB/WQw9TeeYrwGs1hxBHuJh16srwhLyDrbMvQP06qh8R 23 | 48F8UXXSRec22dV9MQphaROhu2qZdv1AC0WD3tqov6L33aqmEOi+xi8JgbT/PLk5 24 | c/c1AoGBAI1A/02ryksW6/wc7/6SP2M2rTy4m1sD/GnrTc67EHnRcVBdKO6qH2RY 25 | nqC8YcveC2ZghgPTDsA3VGuzuBXpwY6wTyV99q6jxQJ6/xcrD9/NUG6Uwv/xfCxl 26 | IJLeBYEqQundSSny3VtaAUK8Ul1nxpTvVRNwtcyWTo8RHAAyNPWd 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | 16 | // +build tools 17 | 18 | package rpcbench 19 | 20 | import ( 21 | _ "github.com/gogo/protobuf/protoc-gen-gogofaster" 22 | _ "golang.org/x/perf/cmd/benchstat" 23 | _ "honnef.co/go/tools/cmd/staticcheck" 24 | ) 25 | -------------------------------------------------------------------------------- /wire.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: wire.proto 3 | 4 | package rpcbench 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/gogo/protobuf/proto" 9 | io "io" 10 | math "math" 11 | math_bits "math/bits" 12 | ) 13 | 14 | // Reference imports to suppress errors if they are not otherwise used. 15 | var _ = proto.Marshal 16 | var _ = fmt.Errorf 17 | var _ = math.Inf 18 | 19 | // This is a compile-time assertion to ensure that this generated file 20 | // is compatible with the proto package it is being compiled against. 21 | // A compilation error at this line likely means your copy of the 22 | // proto package needs to be updated. 23 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 24 | 25 | type CompressionType int32 26 | 27 | const ( 28 | CompressionType_NONE CompressionType = 0 29 | ) 30 | 31 | var CompressionType_name = map[int32]string{ 32 | 0: "NONE", 33 | } 34 | 35 | var CompressionType_value = map[string]int32{ 36 | "NONE": 0, 37 | } 38 | 39 | func (x CompressionType) String() string { 40 | return proto.EnumName(CompressionType_name, int32(x)) 41 | } 42 | 43 | func (CompressionType) EnumDescriptor() ([]byte, []int) { 44 | return fileDescriptor_f2dcdddcdf68d8e0, []int{0} 45 | } 46 | 47 | type RequestHeader struct { 48 | Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 49 | Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` 50 | MethodId int32 `protobuf:"varint,3,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` 51 | Compression CompressionType `protobuf:"varint,4,opt,name=compression,proto3,enum=rpcbench.CompressionType" json:"compression,omitempty"` 52 | UncompressedSize uint32 `protobuf:"varint,5,opt,name=uncompressed_size,json=uncompressedSize,proto3" json:"uncompressed_size,omitempty"` 53 | } 54 | 55 | func (m *RequestHeader) Reset() { *m = RequestHeader{} } 56 | func (m *RequestHeader) String() string { return proto.CompactTextString(m) } 57 | func (*RequestHeader) ProtoMessage() {} 58 | func (*RequestHeader) Descriptor() ([]byte, []int) { 59 | return fileDescriptor_f2dcdddcdf68d8e0, []int{0} 60 | } 61 | func (m *RequestHeader) XXX_Unmarshal(b []byte) error { 62 | return m.Unmarshal(b) 63 | } 64 | func (m *RequestHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 65 | if deterministic { 66 | return xxx_messageInfo_RequestHeader.Marshal(b, m, deterministic) 67 | } else { 68 | b = b[:cap(b)] 69 | n, err := m.MarshalToSizedBuffer(b) 70 | if err != nil { 71 | return nil, err 72 | } 73 | return b[:n], nil 74 | } 75 | } 76 | func (m *RequestHeader) XXX_Merge(src proto.Message) { 77 | xxx_messageInfo_RequestHeader.Merge(m, src) 78 | } 79 | func (m *RequestHeader) XXX_Size() int { 80 | return m.Size() 81 | } 82 | func (m *RequestHeader) XXX_DiscardUnknown() { 83 | xxx_messageInfo_RequestHeader.DiscardUnknown(m) 84 | } 85 | 86 | var xxx_messageInfo_RequestHeader proto.InternalMessageInfo 87 | 88 | func (m *RequestHeader) GetId() uint64 { 89 | if m != nil { 90 | return m.Id 91 | } 92 | return 0 93 | } 94 | 95 | func (m *RequestHeader) GetMethod() string { 96 | if m != nil { 97 | return m.Method 98 | } 99 | return "" 100 | } 101 | 102 | func (m *RequestHeader) GetMethodId() int32 { 103 | if m != nil { 104 | return m.MethodId 105 | } 106 | return 0 107 | } 108 | 109 | func (m *RequestHeader) GetCompression() CompressionType { 110 | if m != nil { 111 | return m.Compression 112 | } 113 | return CompressionType_NONE 114 | } 115 | 116 | func (m *RequestHeader) GetUncompressedSize() uint32 { 117 | if m != nil { 118 | return m.UncompressedSize 119 | } 120 | return 0 121 | } 122 | 123 | type ResponseHeader struct { 124 | Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 125 | Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` 126 | Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` 127 | Compression CompressionType `protobuf:"varint,4,opt,name=compression,proto3,enum=rpcbench.CompressionType" json:"compression,omitempty"` 128 | UncompressedSize uint32 `protobuf:"varint,5,opt,name=uncompressed_size,json=uncompressedSize,proto3" json:"uncompressed_size,omitempty"` 129 | } 130 | 131 | func (m *ResponseHeader) Reset() { *m = ResponseHeader{} } 132 | func (m *ResponseHeader) String() string { return proto.CompactTextString(m) } 133 | func (*ResponseHeader) ProtoMessage() {} 134 | func (*ResponseHeader) Descriptor() ([]byte, []int) { 135 | return fileDescriptor_f2dcdddcdf68d8e0, []int{1} 136 | } 137 | func (m *ResponseHeader) XXX_Unmarshal(b []byte) error { 138 | return m.Unmarshal(b) 139 | } 140 | func (m *ResponseHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 141 | if deterministic { 142 | return xxx_messageInfo_ResponseHeader.Marshal(b, m, deterministic) 143 | } else { 144 | b = b[:cap(b)] 145 | n, err := m.MarshalToSizedBuffer(b) 146 | if err != nil { 147 | return nil, err 148 | } 149 | return b[:n], nil 150 | } 151 | } 152 | func (m *ResponseHeader) XXX_Merge(src proto.Message) { 153 | xxx_messageInfo_ResponseHeader.Merge(m, src) 154 | } 155 | func (m *ResponseHeader) XXX_Size() int { 156 | return m.Size() 157 | } 158 | func (m *ResponseHeader) XXX_DiscardUnknown() { 159 | xxx_messageInfo_ResponseHeader.DiscardUnknown(m) 160 | } 161 | 162 | var xxx_messageInfo_ResponseHeader proto.InternalMessageInfo 163 | 164 | func (m *ResponseHeader) GetId() uint64 { 165 | if m != nil { 166 | return m.Id 167 | } 168 | return 0 169 | } 170 | 171 | func (m *ResponseHeader) GetMethod() string { 172 | if m != nil { 173 | return m.Method 174 | } 175 | return "" 176 | } 177 | 178 | func (m *ResponseHeader) GetError() string { 179 | if m != nil { 180 | return m.Error 181 | } 182 | return "" 183 | } 184 | 185 | func (m *ResponseHeader) GetCompression() CompressionType { 186 | if m != nil { 187 | return m.Compression 188 | } 189 | return CompressionType_NONE 190 | } 191 | 192 | func (m *ResponseHeader) GetUncompressedSize() uint32 { 193 | if m != nil { 194 | return m.UncompressedSize 195 | } 196 | return 0 197 | } 198 | 199 | func init() { 200 | proto.RegisterEnum("rpcbench.CompressionType", CompressionType_name, CompressionType_value) 201 | proto.RegisterType((*RequestHeader)(nil), "rpcbench.RequestHeader") 202 | proto.RegisterType((*ResponseHeader)(nil), "rpcbench.ResponseHeader") 203 | } 204 | 205 | func init() { proto.RegisterFile("wire.proto", fileDescriptor_f2dcdddcdf68d8e0) } 206 | 207 | var fileDescriptor_f2dcdddcdf68d8e0 = []byte{ 208 | // 267 bytes of a gzipped FileDescriptorProto 209 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xcf, 0x2c, 0x4a, 210 | 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x2a, 0x48, 0x4e, 0x4a, 0xcd, 0x4b, 0xce, 211 | 0x50, 0xda, 0xc7, 0xc8, 0xc5, 0x1b, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0xe2, 0x91, 0x9a, 0x98, 212 | 0x92, 0x5a, 0x24, 0xc4, 0xc7, 0xc5, 0x94, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x12, 0xc4, 213 | 0x94, 0x99, 0x22, 0x24, 0xc6, 0xc5, 0x96, 0x9b, 0x5a, 0x92, 0x91, 0x9f, 0x22, 0xc1, 0xa4, 0xc0, 214 | 0xa8, 0xc1, 0x19, 0x04, 0xe5, 0x09, 0x49, 0x73, 0x71, 0x42, 0x58, 0xf1, 0x99, 0x29, 0x12, 0xcc, 215 | 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x1c, 0x10, 0x01, 0xcf, 0x14, 0x21, 0x6b, 0x2e, 0xee, 0xe4, 0xfc, 216 | 0xdc, 0x82, 0xa2, 0xd4, 0xe2, 0xe2, 0xcc, 0xfc, 0x3c, 0x09, 0x16, 0x05, 0x46, 0x0d, 0x3e, 0x23, 217 | 0x49, 0x3d, 0x98, 0xb5, 0x7a, 0xce, 0x08, 0xc9, 0x90, 0xca, 0x82, 0xd4, 0x20, 0x64, 0xd5, 0x42, 218 | 0xda, 0x5c, 0x82, 0xa5, 0x79, 0x30, 0x81, 0xd4, 0x94, 0xf8, 0xe2, 0xcc, 0xaa, 0x54, 0x09, 0x56, 219 | 0x05, 0x46, 0x0d, 0xde, 0x20, 0x01, 0x64, 0x89, 0xe0, 0xcc, 0xaa, 0x54, 0xa5, 0x1d, 0x8c, 0x5c, 220 | 0x7c, 0x41, 0xa9, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x24, 0xfa, 0x40, 0x84, 0x8b, 0x35, 0xb5, 221 | 0xa8, 0x28, 0xbf, 0x08, 0xec, 0x7a, 0xce, 0x20, 0x08, 0x87, 0x7e, 0x4e, 0xd7, 0x92, 0xe6, 0xe2, 222 | 0x47, 0x33, 0x4c, 0x88, 0x83, 0x8b, 0xc5, 0xcf, 0xdf, 0xcf, 0x55, 0x80, 0xc1, 0x49, 0xe2, 0xc4, 223 | 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 224 | 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0x92, 0xd8, 0xc0, 0x71, 0x68, 0x0c, 0x08, 0x00, 225 | 0x00, 0xff, 0xff, 0xdf, 0xd2, 0x99, 0xea, 0xd1, 0x01, 0x00, 0x00, 226 | } 227 | 228 | func (m *RequestHeader) Marshal() (dAtA []byte, err error) { 229 | size := m.Size() 230 | dAtA = make([]byte, size) 231 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 232 | if err != nil { 233 | return nil, err 234 | } 235 | return dAtA[:n], nil 236 | } 237 | 238 | func (m *RequestHeader) MarshalTo(dAtA []byte) (int, error) { 239 | size := m.Size() 240 | return m.MarshalToSizedBuffer(dAtA[:size]) 241 | } 242 | 243 | func (m *RequestHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { 244 | i := len(dAtA) 245 | _ = i 246 | var l int 247 | _ = l 248 | if m.UncompressedSize != 0 { 249 | i = encodeVarintWire(dAtA, i, uint64(m.UncompressedSize)) 250 | i-- 251 | dAtA[i] = 0x28 252 | } 253 | if m.Compression != 0 { 254 | i = encodeVarintWire(dAtA, i, uint64(m.Compression)) 255 | i-- 256 | dAtA[i] = 0x20 257 | } 258 | if m.MethodId != 0 { 259 | i = encodeVarintWire(dAtA, i, uint64(m.MethodId)) 260 | i-- 261 | dAtA[i] = 0x18 262 | } 263 | if len(m.Method) > 0 { 264 | i -= len(m.Method) 265 | copy(dAtA[i:], m.Method) 266 | i = encodeVarintWire(dAtA, i, uint64(len(m.Method))) 267 | i-- 268 | dAtA[i] = 0x12 269 | } 270 | if m.Id != 0 { 271 | i = encodeVarintWire(dAtA, i, uint64(m.Id)) 272 | i-- 273 | dAtA[i] = 0x8 274 | } 275 | return len(dAtA) - i, nil 276 | } 277 | 278 | func (m *ResponseHeader) Marshal() (dAtA []byte, err error) { 279 | size := m.Size() 280 | dAtA = make([]byte, size) 281 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 282 | if err != nil { 283 | return nil, err 284 | } 285 | return dAtA[:n], nil 286 | } 287 | 288 | func (m *ResponseHeader) MarshalTo(dAtA []byte) (int, error) { 289 | size := m.Size() 290 | return m.MarshalToSizedBuffer(dAtA[:size]) 291 | } 292 | 293 | func (m *ResponseHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { 294 | i := len(dAtA) 295 | _ = i 296 | var l int 297 | _ = l 298 | if m.UncompressedSize != 0 { 299 | i = encodeVarintWire(dAtA, i, uint64(m.UncompressedSize)) 300 | i-- 301 | dAtA[i] = 0x28 302 | } 303 | if m.Compression != 0 { 304 | i = encodeVarintWire(dAtA, i, uint64(m.Compression)) 305 | i-- 306 | dAtA[i] = 0x20 307 | } 308 | if len(m.Error) > 0 { 309 | i -= len(m.Error) 310 | copy(dAtA[i:], m.Error) 311 | i = encodeVarintWire(dAtA, i, uint64(len(m.Error))) 312 | i-- 313 | dAtA[i] = 0x1a 314 | } 315 | if len(m.Method) > 0 { 316 | i -= len(m.Method) 317 | copy(dAtA[i:], m.Method) 318 | i = encodeVarintWire(dAtA, i, uint64(len(m.Method))) 319 | i-- 320 | dAtA[i] = 0x12 321 | } 322 | if m.Id != 0 { 323 | i = encodeVarintWire(dAtA, i, uint64(m.Id)) 324 | i-- 325 | dAtA[i] = 0x8 326 | } 327 | return len(dAtA) - i, nil 328 | } 329 | 330 | func encodeVarintWire(dAtA []byte, offset int, v uint64) int { 331 | offset -= sovWire(v) 332 | base := offset 333 | for v >= 1<<7 { 334 | dAtA[offset] = uint8(v&0x7f | 0x80) 335 | v >>= 7 336 | offset++ 337 | } 338 | dAtA[offset] = uint8(v) 339 | return base 340 | } 341 | func (m *RequestHeader) Size() (n int) { 342 | if m == nil { 343 | return 0 344 | } 345 | var l int 346 | _ = l 347 | if m.Id != 0 { 348 | n += 1 + sovWire(uint64(m.Id)) 349 | } 350 | l = len(m.Method) 351 | if l > 0 { 352 | n += 1 + l + sovWire(uint64(l)) 353 | } 354 | if m.MethodId != 0 { 355 | n += 1 + sovWire(uint64(m.MethodId)) 356 | } 357 | if m.Compression != 0 { 358 | n += 1 + sovWire(uint64(m.Compression)) 359 | } 360 | if m.UncompressedSize != 0 { 361 | n += 1 + sovWire(uint64(m.UncompressedSize)) 362 | } 363 | return n 364 | } 365 | 366 | func (m *ResponseHeader) Size() (n int) { 367 | if m == nil { 368 | return 0 369 | } 370 | var l int 371 | _ = l 372 | if m.Id != 0 { 373 | n += 1 + sovWire(uint64(m.Id)) 374 | } 375 | l = len(m.Method) 376 | if l > 0 { 377 | n += 1 + l + sovWire(uint64(l)) 378 | } 379 | l = len(m.Error) 380 | if l > 0 { 381 | n += 1 + l + sovWire(uint64(l)) 382 | } 383 | if m.Compression != 0 { 384 | n += 1 + sovWire(uint64(m.Compression)) 385 | } 386 | if m.UncompressedSize != 0 { 387 | n += 1 + sovWire(uint64(m.UncompressedSize)) 388 | } 389 | return n 390 | } 391 | 392 | func sovWire(x uint64) (n int) { 393 | return (math_bits.Len64(x|1) + 6) / 7 394 | } 395 | func sozWire(x uint64) (n int) { 396 | return sovWire(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 397 | } 398 | func (m *RequestHeader) Unmarshal(dAtA []byte) error { 399 | l := len(dAtA) 400 | iNdEx := 0 401 | for iNdEx < l { 402 | preIndex := iNdEx 403 | var wire uint64 404 | for shift := uint(0); ; shift += 7 { 405 | if shift >= 64 { 406 | return ErrIntOverflowWire 407 | } 408 | if iNdEx >= l { 409 | return io.ErrUnexpectedEOF 410 | } 411 | b := dAtA[iNdEx] 412 | iNdEx++ 413 | wire |= uint64(b&0x7F) << shift 414 | if b < 0x80 { 415 | break 416 | } 417 | } 418 | fieldNum := int32(wire >> 3) 419 | wireType := int(wire & 0x7) 420 | if wireType == 4 { 421 | return fmt.Errorf("proto: RequestHeader: wiretype end group for non-group") 422 | } 423 | if fieldNum <= 0 { 424 | return fmt.Errorf("proto: RequestHeader: illegal tag %d (wire type %d)", fieldNum, wire) 425 | } 426 | switch fieldNum { 427 | case 1: 428 | if wireType != 0 { 429 | return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) 430 | } 431 | m.Id = 0 432 | for shift := uint(0); ; shift += 7 { 433 | if shift >= 64 { 434 | return ErrIntOverflowWire 435 | } 436 | if iNdEx >= l { 437 | return io.ErrUnexpectedEOF 438 | } 439 | b := dAtA[iNdEx] 440 | iNdEx++ 441 | m.Id |= uint64(b&0x7F) << shift 442 | if b < 0x80 { 443 | break 444 | } 445 | } 446 | case 2: 447 | if wireType != 2 { 448 | return fmt.Errorf("proto: wrong wireType = %d for field Method", wireType) 449 | } 450 | var stringLen uint64 451 | for shift := uint(0); ; shift += 7 { 452 | if shift >= 64 { 453 | return ErrIntOverflowWire 454 | } 455 | if iNdEx >= l { 456 | return io.ErrUnexpectedEOF 457 | } 458 | b := dAtA[iNdEx] 459 | iNdEx++ 460 | stringLen |= uint64(b&0x7F) << shift 461 | if b < 0x80 { 462 | break 463 | } 464 | } 465 | intStringLen := int(stringLen) 466 | if intStringLen < 0 { 467 | return ErrInvalidLengthWire 468 | } 469 | postIndex := iNdEx + intStringLen 470 | if postIndex < 0 { 471 | return ErrInvalidLengthWire 472 | } 473 | if postIndex > l { 474 | return io.ErrUnexpectedEOF 475 | } 476 | m.Method = string(dAtA[iNdEx:postIndex]) 477 | iNdEx = postIndex 478 | case 3: 479 | if wireType != 0 { 480 | return fmt.Errorf("proto: wrong wireType = %d for field MethodId", wireType) 481 | } 482 | m.MethodId = 0 483 | for shift := uint(0); ; shift += 7 { 484 | if shift >= 64 { 485 | return ErrIntOverflowWire 486 | } 487 | if iNdEx >= l { 488 | return io.ErrUnexpectedEOF 489 | } 490 | b := dAtA[iNdEx] 491 | iNdEx++ 492 | m.MethodId |= int32(b&0x7F) << shift 493 | if b < 0x80 { 494 | break 495 | } 496 | } 497 | case 4: 498 | if wireType != 0 { 499 | return fmt.Errorf("proto: wrong wireType = %d for field Compression", wireType) 500 | } 501 | m.Compression = 0 502 | for shift := uint(0); ; shift += 7 { 503 | if shift >= 64 { 504 | return ErrIntOverflowWire 505 | } 506 | if iNdEx >= l { 507 | return io.ErrUnexpectedEOF 508 | } 509 | b := dAtA[iNdEx] 510 | iNdEx++ 511 | m.Compression |= CompressionType(b&0x7F) << shift 512 | if b < 0x80 { 513 | break 514 | } 515 | } 516 | case 5: 517 | if wireType != 0 { 518 | return fmt.Errorf("proto: wrong wireType = %d for field UncompressedSize", wireType) 519 | } 520 | m.UncompressedSize = 0 521 | for shift := uint(0); ; shift += 7 { 522 | if shift >= 64 { 523 | return ErrIntOverflowWire 524 | } 525 | if iNdEx >= l { 526 | return io.ErrUnexpectedEOF 527 | } 528 | b := dAtA[iNdEx] 529 | iNdEx++ 530 | m.UncompressedSize |= uint32(b&0x7F) << shift 531 | if b < 0x80 { 532 | break 533 | } 534 | } 535 | default: 536 | iNdEx = preIndex 537 | skippy, err := skipWire(dAtA[iNdEx:]) 538 | if err != nil { 539 | return err 540 | } 541 | if skippy < 0 { 542 | return ErrInvalidLengthWire 543 | } 544 | if (iNdEx + skippy) < 0 { 545 | return ErrInvalidLengthWire 546 | } 547 | if (iNdEx + skippy) > l { 548 | return io.ErrUnexpectedEOF 549 | } 550 | iNdEx += skippy 551 | } 552 | } 553 | 554 | if iNdEx > l { 555 | return io.ErrUnexpectedEOF 556 | } 557 | return nil 558 | } 559 | func (m *ResponseHeader) Unmarshal(dAtA []byte) error { 560 | l := len(dAtA) 561 | iNdEx := 0 562 | for iNdEx < l { 563 | preIndex := iNdEx 564 | var wire uint64 565 | for shift := uint(0); ; shift += 7 { 566 | if shift >= 64 { 567 | return ErrIntOverflowWire 568 | } 569 | if iNdEx >= l { 570 | return io.ErrUnexpectedEOF 571 | } 572 | b := dAtA[iNdEx] 573 | iNdEx++ 574 | wire |= uint64(b&0x7F) << shift 575 | if b < 0x80 { 576 | break 577 | } 578 | } 579 | fieldNum := int32(wire >> 3) 580 | wireType := int(wire & 0x7) 581 | if wireType == 4 { 582 | return fmt.Errorf("proto: ResponseHeader: wiretype end group for non-group") 583 | } 584 | if fieldNum <= 0 { 585 | return fmt.Errorf("proto: ResponseHeader: illegal tag %d (wire type %d)", fieldNum, wire) 586 | } 587 | switch fieldNum { 588 | case 1: 589 | if wireType != 0 { 590 | return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) 591 | } 592 | m.Id = 0 593 | for shift := uint(0); ; shift += 7 { 594 | if shift >= 64 { 595 | return ErrIntOverflowWire 596 | } 597 | if iNdEx >= l { 598 | return io.ErrUnexpectedEOF 599 | } 600 | b := dAtA[iNdEx] 601 | iNdEx++ 602 | m.Id |= uint64(b&0x7F) << shift 603 | if b < 0x80 { 604 | break 605 | } 606 | } 607 | case 2: 608 | if wireType != 2 { 609 | return fmt.Errorf("proto: wrong wireType = %d for field Method", wireType) 610 | } 611 | var stringLen uint64 612 | for shift := uint(0); ; shift += 7 { 613 | if shift >= 64 { 614 | return ErrIntOverflowWire 615 | } 616 | if iNdEx >= l { 617 | return io.ErrUnexpectedEOF 618 | } 619 | b := dAtA[iNdEx] 620 | iNdEx++ 621 | stringLen |= uint64(b&0x7F) << shift 622 | if b < 0x80 { 623 | break 624 | } 625 | } 626 | intStringLen := int(stringLen) 627 | if intStringLen < 0 { 628 | return ErrInvalidLengthWire 629 | } 630 | postIndex := iNdEx + intStringLen 631 | if postIndex < 0 { 632 | return ErrInvalidLengthWire 633 | } 634 | if postIndex > l { 635 | return io.ErrUnexpectedEOF 636 | } 637 | m.Method = string(dAtA[iNdEx:postIndex]) 638 | iNdEx = postIndex 639 | case 3: 640 | if wireType != 2 { 641 | return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) 642 | } 643 | var stringLen uint64 644 | for shift := uint(0); ; shift += 7 { 645 | if shift >= 64 { 646 | return ErrIntOverflowWire 647 | } 648 | if iNdEx >= l { 649 | return io.ErrUnexpectedEOF 650 | } 651 | b := dAtA[iNdEx] 652 | iNdEx++ 653 | stringLen |= uint64(b&0x7F) << shift 654 | if b < 0x80 { 655 | break 656 | } 657 | } 658 | intStringLen := int(stringLen) 659 | if intStringLen < 0 { 660 | return ErrInvalidLengthWire 661 | } 662 | postIndex := iNdEx + intStringLen 663 | if postIndex < 0 { 664 | return ErrInvalidLengthWire 665 | } 666 | if postIndex > l { 667 | return io.ErrUnexpectedEOF 668 | } 669 | m.Error = string(dAtA[iNdEx:postIndex]) 670 | iNdEx = postIndex 671 | case 4: 672 | if wireType != 0 { 673 | return fmt.Errorf("proto: wrong wireType = %d for field Compression", wireType) 674 | } 675 | m.Compression = 0 676 | for shift := uint(0); ; shift += 7 { 677 | if shift >= 64 { 678 | return ErrIntOverflowWire 679 | } 680 | if iNdEx >= l { 681 | return io.ErrUnexpectedEOF 682 | } 683 | b := dAtA[iNdEx] 684 | iNdEx++ 685 | m.Compression |= CompressionType(b&0x7F) << shift 686 | if b < 0x80 { 687 | break 688 | } 689 | } 690 | case 5: 691 | if wireType != 0 { 692 | return fmt.Errorf("proto: wrong wireType = %d for field UncompressedSize", wireType) 693 | } 694 | m.UncompressedSize = 0 695 | for shift := uint(0); ; shift += 7 { 696 | if shift >= 64 { 697 | return ErrIntOverflowWire 698 | } 699 | if iNdEx >= l { 700 | return io.ErrUnexpectedEOF 701 | } 702 | b := dAtA[iNdEx] 703 | iNdEx++ 704 | m.UncompressedSize |= uint32(b&0x7F) << shift 705 | if b < 0x80 { 706 | break 707 | } 708 | } 709 | default: 710 | iNdEx = preIndex 711 | skippy, err := skipWire(dAtA[iNdEx:]) 712 | if err != nil { 713 | return err 714 | } 715 | if skippy < 0 { 716 | return ErrInvalidLengthWire 717 | } 718 | if (iNdEx + skippy) < 0 { 719 | return ErrInvalidLengthWire 720 | } 721 | if (iNdEx + skippy) > l { 722 | return io.ErrUnexpectedEOF 723 | } 724 | iNdEx += skippy 725 | } 726 | } 727 | 728 | if iNdEx > l { 729 | return io.ErrUnexpectedEOF 730 | } 731 | return nil 732 | } 733 | func skipWire(dAtA []byte) (n int, err error) { 734 | l := len(dAtA) 735 | iNdEx := 0 736 | depth := 0 737 | for iNdEx < l { 738 | var wire uint64 739 | for shift := uint(0); ; shift += 7 { 740 | if shift >= 64 { 741 | return 0, ErrIntOverflowWire 742 | } 743 | if iNdEx >= l { 744 | return 0, io.ErrUnexpectedEOF 745 | } 746 | b := dAtA[iNdEx] 747 | iNdEx++ 748 | wire |= (uint64(b) & 0x7F) << shift 749 | if b < 0x80 { 750 | break 751 | } 752 | } 753 | wireType := int(wire & 0x7) 754 | switch wireType { 755 | case 0: 756 | for shift := uint(0); ; shift += 7 { 757 | if shift >= 64 { 758 | return 0, ErrIntOverflowWire 759 | } 760 | if iNdEx >= l { 761 | return 0, io.ErrUnexpectedEOF 762 | } 763 | iNdEx++ 764 | if dAtA[iNdEx-1] < 0x80 { 765 | break 766 | } 767 | } 768 | case 1: 769 | iNdEx += 8 770 | case 2: 771 | var length int 772 | for shift := uint(0); ; shift += 7 { 773 | if shift >= 64 { 774 | return 0, ErrIntOverflowWire 775 | } 776 | if iNdEx >= l { 777 | return 0, io.ErrUnexpectedEOF 778 | } 779 | b := dAtA[iNdEx] 780 | iNdEx++ 781 | length |= (int(b) & 0x7F) << shift 782 | if b < 0x80 { 783 | break 784 | } 785 | } 786 | if length < 0 { 787 | return 0, ErrInvalidLengthWire 788 | } 789 | iNdEx += length 790 | case 3: 791 | depth++ 792 | case 4: 793 | if depth == 0 { 794 | return 0, ErrUnexpectedEndOfGroupWire 795 | } 796 | depth-- 797 | case 5: 798 | iNdEx += 4 799 | default: 800 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 801 | } 802 | if iNdEx < 0 { 803 | return 0, ErrInvalidLengthWire 804 | } 805 | if depth == 0 { 806 | return iNdEx, nil 807 | } 808 | } 809 | return 0, io.ErrUnexpectedEOF 810 | } 811 | 812 | var ( 813 | ErrInvalidLengthWire = fmt.Errorf("proto: negative length found during unmarshaling") 814 | ErrIntOverflowWire = fmt.Errorf("proto: integer overflow") 815 | ErrUnexpectedEndOfGroupWire = fmt.Errorf("proto: unexpected end of group") 816 | ) 817 | -------------------------------------------------------------------------------- /wire.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Cockroach Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | // implied. See the License for the specific language governing 13 | // permissions and limitations under the License. See the AUTHORS file 14 | // for names of contributors. 15 | // 16 | // Author: Peter Mattis (peter@cockroachlabs.com) 17 | 18 | // Copyright 2013 . All rights reserved. 19 | // Use of this source code is governed by a BSD-style 20 | // license that can be found in the LICENSE file. 21 | 22 | // protorpc wire format wrapper 23 | // 24 | // 0. Frame Format 25 | // len : uvarint64 26 | // data: byte[len] 27 | // 28 | // 1. Client Send Request 29 | // Send RequestHeader: sendFrame(conn, hdr, len(hdr)) 30 | // Send Request: sendFrame(conn, body, len(body)) 31 | // 32 | // 2. Server Recv Request 33 | // Recv RequestHeader: recvFrame(conn, hdr, max_hdr_len, 0) 34 | // Recv Request: recvFrame(conn, body) 35 | // 36 | // 3. Server Send Response 37 | // Send ResponseHeader: sendFrame(conn, hdr, len(hdr)) 38 | // Send Response: sendFrame(conn, body, len(body)) 39 | // 40 | // 4. Client Recv Response 41 | // Recv ResponseHeader: recvFrame(conn, hdr, max_hdr_len, 0) 42 | // Recv Response: recvFrame(conn, body) 43 | syntax = "proto3"; 44 | 45 | package rpcbench; 46 | 47 | enum CompressionType { 48 | NONE = 0; 49 | } 50 | 51 | message RequestHeader { 52 | uint64 id = 1; 53 | string method = 2; 54 | int32 method_id = 3; 55 | CompressionType compression = 4; 56 | uint32 uncompressed_size = 5; 57 | } 58 | 59 | message ResponseHeader { 60 | uint64 id = 1; 61 | string method = 2; 62 | string error = 3; 63 | CompressionType compression = 4; 64 | uint32 uncompressed_size = 5; 65 | } 66 | --------------------------------------------------------------------------------