Reduce allocations (#17584)

* Reduce allocations

* Add stringsHasPrefixFold which can compare string prefixes, while ignoring case and not allocating.
* Reuse all msgp.Readers
* Reuse metadata buffers when not reading data.

* Make type safe. Make buffer 4K instead of 8.

* Unslice
This commit is contained in:
Klaus Post
2023-07-06 16:02:08 -07:00
committed by GitHub
parent 1bf23374a3
commit ff5988f4e0
21 changed files with 67 additions and 36 deletions

View File

@@ -227,7 +227,8 @@ func (client *storageRESTClient) NSScanner(ctx context.Context, cache dataUsageC
rw.CloseWithError(waitForHTTPStream(respBody, rw))
}()
ms := msgp.NewReader(rr)
ms := msgpNewReader(rr)
defer readMsgpReaderPoolPut(ms)
for {
// Read whether it is an update.
upd, err := ms.ReadBool()
@@ -498,16 +499,24 @@ var readMsgpReaderPool = sync.Pool{New: func() interface{} { return &msgp.Reader
// mspNewReader returns a *Reader that reads from the provided reader.
// The reader will be buffered.
// Return with readMsgpReaderPoolPut when done.
func msgpNewReader(r io.Reader) *msgp.Reader {
p := readMsgpReaderPool.Get().(*msgp.Reader)
if p.R == nil {
p.R = xbufio.NewReaderSize(r, 8<<10)
p.R = xbufio.NewReaderSize(r, 4<<10)
} else {
p.R.Reset(r)
}
return p
}
// readMsgpReaderPoolPut can be used to reuse a *msgp.Reader.
func readMsgpReaderPoolPut(r *msgp.Reader) {
if r != nil {
readMsgpReaderPool.Put(r)
}
}
func (client *storageRESTClient) ReadVersion(ctx context.Context, volume, path, versionID string, readData bool) (fi FileInfo, err error) {
values := make(url.Values)
values.Set(storageRESTVolume, volume)
@@ -522,7 +531,7 @@ func (client *storageRESTClient) ReadVersion(ctx context.Context, volume, path,
defer xhttp.DrainBody(respBody)
dec := msgpNewReader(respBody)
defer readMsgpReaderPool.Put(dec)
defer readMsgpReaderPoolPut(dec)
err = fi.DecodeMsg(dec)
return fi, err
@@ -541,7 +550,7 @@ func (client *storageRESTClient) ReadXL(ctx context.Context, volume string, path
defer xhttp.DrainBody(respBody)
dec := msgpNewReader(respBody)
defer readMsgpReaderPool.Put(dec)
defer readMsgpReaderPoolPut(dec)
err = rf.DecodeMsg(dec)
return rf, err
@@ -735,7 +744,7 @@ func (client *storageRESTClient) StatInfoFile(ctx context.Context, volume, path
return stat, err
}
rd := msgpNewReader(respReader)
defer readMsgpReaderPool.Put(rd)
defer readMsgpReaderPoolPut(rd)
for {
var st StatInfo
err = st.DecodeMsg(rd)
@@ -774,6 +783,7 @@ func (client *storageRESTClient) ReadMultiple(ctx context.Context, req ReadMulti
pw.CloseWithError(waitForHTTPStream(respBody, pw))
}()
mr := msgp.NewReader(pr)
defer readMsgpReaderPoolPut(mr)
for {
var file ReadMultipleResp
if err := file.DecodeMsg(mr); err != nil {