3939 "to the current connection or connection pool" )
4040)
4141
42+ var slicePool = & sync.Pool {
43+ New : func () interface {} {
44+ buf := make ([]byte , 1024 )
45+ return & buf
46+ },
47+ }
48+
4249const (
4350 // Connected signals that connection is established or reestablished.
4451 Connected ConnEventKind = iota + 1
@@ -373,7 +380,6 @@ func Connect(ctx context.Context, dialer Dialer, opts Opts) (conn *Connection, e
373380 }
374381
375382 conn .cond = sync .NewCond (& conn .mutex )
376-
377383 if conn .opts .Reconnect > 0 {
378384 // We don't need these mutex.Lock()/mutex.Unlock() here, but
379385 // runReconnects() expects mutex.Lock() to be set, so it's
@@ -844,12 +850,36 @@ func readWatchEvent(reader io.Reader) (connWatchEvent, error) {
844850 return event , nil
845851}
846852
853+ func getSlice (length int ) * []byte {
854+ bs , ok := slicePool .Get ().(* []byte )
855+
856+ if ok && cap (* bs ) >= int (length ) {
857+ clear ((* bs )[:cap (* bs )])
858+ * bs = (* bs )[:length ]
859+ return bs
860+ }
861+
862+ if ok {
863+ slicePool .Put (bs )
864+ }
865+
866+ b := make ([]byte , length )
867+
868+ return & b
869+ }
870+
871+ func putSlice (buf * []byte ) {
872+ slicePool .Put (buf )
873+ }
874+
847875func (conn * Connection ) reader (r io.Reader , c Conn ) {
848876 events := make (chan connWatchEvent , 1024 )
849877 defer close (events )
850878
851879 go conn .eventer (events )
852880
881+ buf := & smallBuf {}
882+
853883 for atomic .LoadUint32 (& conn .state ) != connClosed {
854884 respBytes , err := read (r , conn .lenbuf [:])
855885 if err != nil {
@@ -860,8 +890,12 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
860890 conn .reconnect (err , c )
861891 return
862892 }
863- buf := smallBuf {b : respBytes }
864- header , code , err := decodeHeader (conn .dec , & buf )
893+
894+ buf .b = * respBytes
895+ buf .p = 0
896+ buf .ptr = respBytes
897+
898+ header , code , err := decodeHeader (conn .dec , buf )
865899 if err != nil {
866900 err = ClientError {
867901 ErrProtocolError ,
@@ -873,7 +907,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
873907
874908 var fut * future = nil
875909 if code == iproto .IPROTO_EVENT {
876- if event , err := readWatchEvent (& buf ); err == nil {
910+ if event , err := readWatchEvent (buf ); err == nil {
877911 events <- event
878912 } else {
879913 err = ClientError {
@@ -887,7 +921,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
887921 conn .opts .Logger .Report (LogBoxSessionPushUnsupported , conn , header )
888922 } else {
889923 if fut = conn .fetchFuture (header .RequestId ); fut != nil {
890- if err := fut .setResponse (header , & buf ); err != nil {
924+ if err := fut .setResponse (header , buf ); err != nil {
891925 fut .setError (fmt .Errorf ("failed to set response: %w" , err ))
892926 }
893927 conn .markDone (fut )
@@ -1190,7 +1224,9 @@ func (conn *Connection) timeouts() {
11901224 }
11911225}
11921226
1193- func read (r io.Reader , lenbuf []byte ) (response []byte , err error ) {
1227+ // read uses args to allocate slices for responses using sync.Pool.
1228+ // data must be released later using Release.
1229+ func read (r io.Reader , lenbuf []byte ) (response * []byte , err error ) {
11941230 var length uint64
11951231
11961232 if _ , err = io .ReadFull (r , lenbuf ); err != nil {
@@ -1214,8 +1250,8 @@ func read(r io.Reader, lenbuf []byte) (response []byte, err error) {
12141250 return
12151251 }
12161252
1217- response = make ([] byte , length )
1218- _ , err = io .ReadFull (r , response )
1253+ response = getSlice ( int ( length ) )
1254+ _ , err = io .ReadFull (r , * response )
12191255
12201256 return
12211257}
0 commit comments