Make IO Buffer size configurable. (#1544)
* Make IO Buffer size configurable. * Fixing typo
This commit is contained in:
@ -163,6 +163,8 @@ func StartServer(info ServerInfo, opts ...grpc.ServerOption) (string, func()) {
|
|||||||
if nw != nil {
|
if nw != nil {
|
||||||
lis = nw.Listener(lis)
|
lis = nw.Listener(lis)
|
||||||
}
|
}
|
||||||
|
opts = append(opts, grpc.WriteBufferSize(128*1024))
|
||||||
|
opts = append(opts, grpc.ReadBufferSize(128*1024))
|
||||||
s := grpc.NewServer(opts...)
|
s := grpc.NewServer(opts...)
|
||||||
switch info.Type {
|
switch info.Type {
|
||||||
case "protobuf":
|
case "protobuf":
|
||||||
@ -236,6 +238,8 @@ func DoByteBufStreamingRoundTrip(stream testpb.BenchmarkService_StreamingCallCli
|
|||||||
|
|
||||||
// NewClientConn creates a gRPC client connection to addr.
|
// NewClientConn creates a gRPC client connection to addr.
|
||||||
func NewClientConn(addr string, opts ...grpc.DialOption) *grpc.ClientConn {
|
func NewClientConn(addr string, opts ...grpc.DialOption) *grpc.ClientConn {
|
||||||
|
opts = append(opts, grpc.WithWriteBufferSize(128*1024))
|
||||||
|
opts = append(opts, grpc.WithReadBufferSize(128*1024))
|
||||||
conn, err := grpc.Dial(addr, opts...)
|
conn, err := grpc.Dial(addr, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Fatalf("NewClientConn(%q) failed to create a ClientConn %v", addr, err)
|
grpclog.Fatalf("NewClientConn(%q) failed to create a ClientConn %v", addr, err)
|
||||||
|
@ -100,6 +100,22 @@ const (
|
|||||||
// DialOption configures how we set up the connection.
|
// DialOption configures how we set up the connection.
|
||||||
type DialOption func(*dialOptions)
|
type DialOption func(*dialOptions)
|
||||||
|
|
||||||
|
// WithWriteBufferSize lets you set the size of write buffer, this determines how much data can be batched
|
||||||
|
// before doing a write on the wire.
|
||||||
|
func WithWriteBufferSize(s int) DialOption {
|
||||||
|
return func(o *dialOptions) {
|
||||||
|
o.copts.WriteBufferSize = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithReadBufferSize lets you set the size of read buffer, this determines how much data can be read at most
|
||||||
|
// for each read syscall.
|
||||||
|
func WithReadBufferSize(s int) DialOption {
|
||||||
|
return func(o *dialOptions) {
|
||||||
|
o.copts.ReadBufferSize = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithInitialWindowSize returns a DialOption which sets the value for initial window size on a stream.
|
// WithInitialWindowSize returns a DialOption which sets the value for initial window size on a stream.
|
||||||
// The lower bound for window size is 64K and any value smaller than that will be ignored.
|
// The lower bound for window size is 64K and any value smaller than that will be ignored.
|
||||||
func WithInitialWindowSize(s int32) DialOption {
|
func WithInitialWindowSize(s int32) DialOption {
|
||||||
|
20
server.go
20
server.go
@ -116,6 +116,8 @@ type options struct {
|
|||||||
keepalivePolicy keepalive.EnforcementPolicy
|
keepalivePolicy keepalive.EnforcementPolicy
|
||||||
initialWindowSize int32
|
initialWindowSize int32
|
||||||
initialConnWindowSize int32
|
initialConnWindowSize int32
|
||||||
|
writeBufferSize int
|
||||||
|
readBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultServerOptions = options{
|
var defaultServerOptions = options{
|
||||||
@ -126,6 +128,22 @@ var defaultServerOptions = options{
|
|||||||
// A ServerOption sets options such as credentials, codec and keepalive parameters, etc.
|
// A ServerOption sets options such as credentials, codec and keepalive parameters, etc.
|
||||||
type ServerOption func(*options)
|
type ServerOption func(*options)
|
||||||
|
|
||||||
|
// WriteBufferSize lets you set the size of write buffer, this determines how much data can be batched
|
||||||
|
// before doing a write on the wire.
|
||||||
|
func WriteBufferSize(s int) ServerOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.writeBufferSize = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBufferSize lets you set the size of read buffer, this determines how much data can be read at most
|
||||||
|
// for one read syscall.
|
||||||
|
func ReadBufferSize(s int) ServerOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.readBufferSize = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// InitialWindowSize returns a ServerOption that sets window size for stream.
|
// InitialWindowSize returns a ServerOption that sets window size for stream.
|
||||||
// The lower bound for window size is 64K and any value smaller than that will be ignored.
|
// The lower bound for window size is 64K and any value smaller than that will be ignored.
|
||||||
func InitialWindowSize(s int32) ServerOption {
|
func InitialWindowSize(s int32) ServerOption {
|
||||||
@ -524,6 +542,8 @@ func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo)
|
|||||||
KeepalivePolicy: s.opts.keepalivePolicy,
|
KeepalivePolicy: s.opts.keepalivePolicy,
|
||||||
InitialWindowSize: s.opts.initialWindowSize,
|
InitialWindowSize: s.opts.initialWindowSize,
|
||||||
InitialConnWindowSize: s.opts.initialConnWindowSize,
|
InitialConnWindowSize: s.opts.initialConnWindowSize,
|
||||||
|
WriteBufferSize: s.opts.writeBufferSize,
|
||||||
|
ReadBufferSize: s.opts.readBufferSize,
|
||||||
}
|
}
|
||||||
st, err := transport.NewServerTransport("http2", c, config)
|
st, err := transport.NewServerTransport("http2", c, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -194,6 +194,14 @@ func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) (
|
|||||||
dynamicWindow = false
|
dynamicWindow = false
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
writeBufSize := defaultWriteBufSize
|
||||||
|
if opts.WriteBufferSize > 0 {
|
||||||
|
writeBufSize = opts.WriteBufferSize
|
||||||
|
}
|
||||||
|
readBufSize := defaultReadBufSize
|
||||||
|
if opts.ReadBufferSize > 0 {
|
||||||
|
readBufSize = opts.ReadBufferSize
|
||||||
|
}
|
||||||
t := &http2Client{
|
t := &http2Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
target: addr.Addr,
|
target: addr.Addr,
|
||||||
@ -209,9 +217,9 @@ func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) (
|
|||||||
errorChan: make(chan struct{}),
|
errorChan: make(chan struct{}),
|
||||||
goAway: make(chan struct{}),
|
goAway: make(chan struct{}),
|
||||||
awakenKeepalive: make(chan struct{}, 1),
|
awakenKeepalive: make(chan struct{}, 1),
|
||||||
framer: newFramer(conn),
|
|
||||||
hBuf: &buf,
|
hBuf: &buf,
|
||||||
hEnc: hpack.NewEncoder(&buf),
|
hEnc: hpack.NewEncoder(&buf),
|
||||||
|
framer: newFramer(conn, writeBufSize, readBufSize),
|
||||||
controlBuf: newControlBuffer(),
|
controlBuf: newControlBuffer(),
|
||||||
fc: &inFlow{limit: uint32(icwz)},
|
fc: &inFlow{limit: uint32(icwz)},
|
||||||
sendQuotaPool: newQuotaPool(defaultWindowSize),
|
sendQuotaPool: newQuotaPool(defaultWindowSize),
|
||||||
|
@ -116,7 +116,15 @@ type http2Server struct {
|
|||||||
// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is
|
// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is
|
||||||
// returned if something goes wrong.
|
// returned if something goes wrong.
|
||||||
func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
|
func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
|
||||||
framer := newFramer(conn)
|
writeBufSize := defaultWriteBufSize
|
||||||
|
if config.WriteBufferSize > 0 {
|
||||||
|
writeBufSize = config.WriteBufferSize
|
||||||
|
}
|
||||||
|
readBufSize := defaultReadBufSize
|
||||||
|
if config.ReadBufferSize > 0 {
|
||||||
|
readBufSize = config.ReadBufferSize
|
||||||
|
}
|
||||||
|
framer := newFramer(conn, writeBufSize, readBufSize)
|
||||||
// Send initial settings as connection preface to client.
|
// Send initial settings as connection preface to client.
|
||||||
var isettings []http2.Setting
|
var isettings []http2.Setting
|
||||||
// TODO(zhaoq): Have a better way to signal "no limit" because 0 is
|
// TODO(zhaoq): Have a better way to signal "no limit" because 0 is
|
||||||
|
@ -44,7 +44,8 @@ const (
|
|||||||
// http://http2.github.io/http2-spec/#SettingValues
|
// http://http2.github.io/http2-spec/#SettingValues
|
||||||
http2InitHeaderTableSize = 4096
|
http2InitHeaderTableSize = 4096
|
||||||
// http2IOBufSize specifies the buffer size for sending frames.
|
// http2IOBufSize specifies the buffer size for sending frames.
|
||||||
http2IOBufSize = 32 * 1024
|
defaultWriteBufSize = 32 * 1024
|
||||||
|
defaultReadBufSize = 32 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -474,10 +475,10 @@ type framer struct {
|
|||||||
fr *http2.Framer
|
fr *http2.Framer
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFramer(conn net.Conn) *framer {
|
func newFramer(conn net.Conn, writeBufferSize, readBufferSize int) *framer {
|
||||||
f := &framer{
|
f := &framer{
|
||||||
reader: bufio.NewReaderSize(conn, http2IOBufSize),
|
reader: bufio.NewReaderSize(conn, readBufferSize),
|
||||||
writer: bufio.NewWriterSize(conn, http2IOBufSize),
|
writer: bufio.NewWriterSize(conn, writeBufferSize),
|
||||||
}
|
}
|
||||||
f.fr = http2.NewFramer(f.writer, f.reader)
|
f.fr = http2.NewFramer(f.writer, f.reader)
|
||||||
// Opt-in to Frame reuse API on framer to reduce garbage.
|
// Opt-in to Frame reuse API on framer to reduce garbage.
|
||||||
|
@ -472,6 +472,8 @@ type ServerConfig struct {
|
|||||||
KeepalivePolicy keepalive.EnforcementPolicy
|
KeepalivePolicy keepalive.EnforcementPolicy
|
||||||
InitialWindowSize int32
|
InitialWindowSize int32
|
||||||
InitialConnWindowSize int32
|
InitialConnWindowSize int32
|
||||||
|
WriteBufferSize int
|
||||||
|
ReadBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServerTransport creates a ServerTransport with conn or non-nil error
|
// NewServerTransport creates a ServerTransport with conn or non-nil error
|
||||||
@ -503,6 +505,10 @@ type ConnectOptions struct {
|
|||||||
InitialWindowSize int32
|
InitialWindowSize int32
|
||||||
// InitialConnWindowSize sets the initial window size for a connection.
|
// InitialConnWindowSize sets the initial window size for a connection.
|
||||||
InitialConnWindowSize int32
|
InitialConnWindowSize int32
|
||||||
|
// WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
|
||||||
|
WriteBufferSize int
|
||||||
|
// ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
|
||||||
|
ReadBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
// TargetInfo contains the information of the target such as network address and metadata.
|
// TargetInfo contains the information of the target such as network address and metadata.
|
||||||
@ -526,7 +532,7 @@ type Options struct {
|
|||||||
|
|
||||||
// Delay is a hint to the transport implementation for whether
|
// Delay is a hint to the transport implementation for whether
|
||||||
// the data could be buffered for a batching write. The
|
// the data could be buffered for a batching write. The
|
||||||
// Transport implementation may ignore the hint.
|
// transport implementation may ignore the hint.
|
||||||
Delay bool
|
Delay bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1989,8 +1989,8 @@ func (s *httpServer) start(t *testing.T, lis net.Listener) {
|
|||||||
t.Errorf("Error at server-side while reading preface from cleint. Err: %v", err)
|
t.Errorf("Error at server-side while reading preface from cleint. Err: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
reader := bufio.NewReaderSize(s.conn, http2IOBufSize)
|
reader := bufio.NewReaderSize(s.conn, defaultWriteBufSize)
|
||||||
writer := bufio.NewWriterSize(s.conn, http2IOBufSize)
|
writer := bufio.NewWriterSize(s.conn, defaultReadBufSize)
|
||||||
framer := http2.NewFramer(writer, reader)
|
framer := http2.NewFramer(writer, reader)
|
||||||
if err = framer.WriteSettingsAck(); err != nil {
|
if err = framer.WriteSettingsAck(); err != nil {
|
||||||
t.Errorf("Error at server-side while sending Settings ack. Err: %v", err)
|
t.Errorf("Error at server-side while sending Settings ack. Err: %v", err)
|
||||||
|
Reference in New Issue
Block a user