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
@@ -843,12 +850,36 @@ func readWatchEvent(reader io.Reader) (connWatchEvent, error) {
843850 return event , nil
844851}
845852
853+ func getSlice (length int ) * []byte {
854+ bs , ok := slicePool .Get ().(* []byte )
855+
856+ if ok && cap (* bs ) >= 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+
846875func (conn * Connection ) reader (r io.Reader , c Conn ) {
847876 events := make (chan connWatchEvent , 1024 )
848877 defer close (events )
849878
850879 go conn .eventer (events )
851880
881+ buf := & smallBuf {}
882+
852883 for atomic .LoadUint32 (& conn .state ) != connClosed {
853884 respBytes , err := read (r , conn .lenbuf [:])
854885 if err != nil {
@@ -860,8 +891,11 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
860891 return
861892 }
862893
863- buf := smallBuf {b : respBytes }
864- header , code , err := decodeHeader (conn .dec , & buf )
894+ buf .b = * respBytes
895+ buf .p = 0
896+ buf .ptr = respBytes
897+
898+ header , code , err := decodeHeader (conn .dec , buf )
865899
866900 if err != nil {
867901 err = ClientError {
@@ -874,7 +908,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
874908
875909 var fut * future = nil
876910 if code == iproto .IPROTO_EVENT {
877- if event , err := readWatchEvent (& buf ); err == nil {
911+ if event , err := readWatchEvent (buf ); err == nil {
878912 events <- event
879913 } else {
880914 err = ClientError {
@@ -888,7 +922,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
888922 conn .opts .Logger .Report (LogBoxSessionPushUnsupported , conn , header )
889923 } else {
890924 if fut = conn .fetchFuture (header .RequestId ); fut != nil {
891- if err := fut .setResponse (header , & buf ); err != nil {
925+ if err := fut .setResponse (header , buf ); err != nil {
892926 fut .setError (fmt .Errorf ("failed to set response: %w" , err ))
893927 }
894928 conn .markDone (fut )
@@ -1191,7 +1225,9 @@ func (conn *Connection) timeouts() {
11911225 }
11921226}
11931227
1194- func read (r io.Reader , lenbuf []byte ) (response []byte , err error ) {
1228+ // read uses args to allocate slices for responses using sync.Pool.
1229+ // data must be released later using Release.
1230+ func read (r io.Reader , lenbuf []byte ) (response * []byte , err error ) {
11951231 var length uint64
11961232
11971233 if _ , err = io .ReadFull (r , lenbuf ); err != nil {
@@ -1215,8 +1251,8 @@ func read(r io.Reader, lenbuf []byte) (response []byte, err error) {
12151251 return
12161252 }
12171253
1218- response = make ([] byte , length )
1219- _ , err = io .ReadFull (r , response )
1254+ response = getSlice ( int ( length ) )
1255+ _ , err = io .ReadFull (r , * response )
12201256
12211257 return
12221258}
0 commit comments