mirror of
https://github.com/minio/minio.git
synced 2025-04-22 11:26:36 -04:00
Reuse small buffers (#12948)
When reading metadata allow reuse of buffers in certain cases. Take the low-hanging fruit. Reduce GC overhead when listing.
This commit is contained in:
parent
3eac02f676
commit
89febdb3d6
@ -36,11 +36,11 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// RFC3339 a subset of the ISO8601 timestamp format. e.g 2014-04-29T18:30:38Z
|
// RFC3339 a subset of the ISO8601 timestamp format. e.g 2014-04-29T18:30:38Z
|
||||||
iso8601TimeFormat = "2006-01-02T15:04:05.000Z" // Reply date format with nanosecond precision.
|
iso8601TimeFormat = "2006-01-02T15:04:05.000Z" // Reply date format with nanosecond precision.
|
||||||
maxObjectList = metacacheBlockSize - (metacacheBlockSize / 10) // Limit number of objects in a listObjectsResponse/listObjectsVersionsResponse.
|
maxObjectList = 1000 // Limit number of objects in a listObjectsResponse/listObjectsVersionsResponse.
|
||||||
maxDeleteList = 10000 // Limit number of objects deleted in a delete call.
|
maxDeleteList = 10000 // Limit number of objects deleted in a delete call.
|
||||||
maxUploadsList = 10000 // Limit number of uploads in a listUploadsResponse.
|
maxUploadsList = 10000 // Limit number of uploads in a listUploadsResponse.
|
||||||
maxPartsList = 10000 // Limit number of parts in a listPartsResponse.
|
maxPartsList = 10000 // Limit number of parts in a listPartsResponse.
|
||||||
)
|
)
|
||||||
|
|
||||||
// LocationResponse - format for location response.
|
// LocationResponse - format for location response.
|
||||||
|
@ -56,10 +56,11 @@ const metacacheStreamVersion = 2
|
|||||||
|
|
||||||
// metacacheWriter provides a serializer of metacache objects.
|
// metacacheWriter provides a serializer of metacache objects.
|
||||||
type metacacheWriter struct {
|
type metacacheWriter struct {
|
||||||
mw *msgp.Writer
|
mw *msgp.Writer
|
||||||
creator func() error
|
creator func() error
|
||||||
closer func() error
|
closer func() error
|
||||||
blockSize int
|
blockSize int
|
||||||
|
reuseBlocks bool
|
||||||
|
|
||||||
streamErr error
|
streamErr error
|
||||||
streamWg sync.WaitGroup
|
streamWg sync.WaitGroup
|
||||||
@ -141,6 +142,9 @@ func (w *metacacheWriter) write(objs ...metaCacheEntry) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if w.reuseBlocks && cap(o.metadata) >= metaDataReadDefault {
|
||||||
|
metaDataPool.Put(o.metadata)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -76,6 +76,7 @@ func (s *xlStorage) WalkDir(ctx context.Context, opts WalkDirOptions, wr io.Writ
|
|||||||
|
|
||||||
// Use a small block size to start sending quickly
|
// Use a small block size to start sending quickly
|
||||||
w := newMetacacheWriter(wr, 16<<10)
|
w := newMetacacheWriter(wr, 16<<10)
|
||||||
|
w.reuseBlocks = true // We are not sharing results, so reuse buffers.
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
out, err := w.stream()
|
out, err := w.stream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cespare/xxhash/v2"
|
"github.com/cespare/xxhash/v2"
|
||||||
@ -1430,20 +1431,26 @@ func (z xlMetaV2) ToFileInfo(volume, path, versionID string) (fi FileInfo, err e
|
|||||||
return FileInfo{}, errFileVersionNotFound
|
return FileInfo{}, errFileVersionNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read at most this much on initial read.
|
||||||
|
const metaDataReadDefault = 4 << 10
|
||||||
|
|
||||||
|
// Return used metadata byte slices here.
|
||||||
|
var metaDataPool = sync.Pool{New: func() interface{} { return make([]byte, 0, metaDataReadDefault) }}
|
||||||
|
|
||||||
// readXLMetaNoData will load the metadata, but skip data segments.
|
// readXLMetaNoData will load the metadata, but skip data segments.
|
||||||
// This should only be used when data is never interesting.
|
// This should only be used when data is never interesting.
|
||||||
// If data is not xlv2, it is returned in full.
|
// If data is not xlv2, it is returned in full.
|
||||||
func readXLMetaNoData(r io.Reader, size int64) ([]byte, error) {
|
func readXLMetaNoData(r io.Reader, size int64) ([]byte, error) {
|
||||||
// Read at most this much on initial read.
|
|
||||||
const readDefault = 4 << 10
|
|
||||||
initial := size
|
initial := size
|
||||||
hasFull := true
|
hasFull := true
|
||||||
if initial > readDefault {
|
if initial > metaDataReadDefault {
|
||||||
initial = readDefault
|
initial = metaDataReadDefault
|
||||||
hasFull = false
|
hasFull = false
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, initial)
|
buf := metaDataPool.Get().([]byte)
|
||||||
|
buf = buf[:initial]
|
||||||
|
|
||||||
_, err := io.ReadFull(r, buf)
|
_, err := io.ReadFull(r, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("readXLMetaNoData.ReadFull: %w", err)
|
return nil, fmt.Errorf("readXLMetaNoData.ReadFull: %w", err)
|
||||||
|
@ -1082,6 +1082,7 @@ func (s *xlStorage) ReadVersion(ctx context.Context, volume, path, versionID str
|
|||||||
err = osErrToFileErr(err)
|
err = osErrToFileErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errFileNotFound {
|
if err == errFileNotFound {
|
||||||
if err = s.renameLegacyMetadata(volumeDir, path); err != nil {
|
if err = s.renameLegacyMetadata(volumeDir, path); err != nil {
|
||||||
@ -1120,6 +1121,13 @@ func (s *xlStorage) ReadVersion(ctx context.Context, volume, path, versionID str
|
|||||||
return fi, err
|
return fi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(fi.Data) == 0 && cap(buf) >= metaDataReadDefault && cap(buf) < metaDataReadDefault*4 {
|
||||||
|
// We did not read inline data, so we have no references.
|
||||||
|
defer func(b []byte) {
|
||||||
|
metaDataPool.Put(buf)
|
||||||
|
}(buf)
|
||||||
|
}
|
||||||
|
|
||||||
if readData {
|
if readData {
|
||||||
if len(fi.Data) > 0 || fi.Size == 0 {
|
if len(fi.Data) > 0 || fi.Size == 0 {
|
||||||
if len(fi.Data) > 0 {
|
if len(fi.Data) > 0 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user