Optimize FileInfo(Version) transfer (#10775)

File Info decoding, in particular, is showing up as a major 
allocator and time consumer for internode data transfers

Switch to message pack for cross-server transfers:

```
MSGP:

Size: 945 bytes

BenchmarkEncodeFileInfoMsgp-32    	 1558444	       866 ns/op	   1.16 MB/s	       0 B/op	       0 allocs/op
BenchmarkDecodeFileInfoMsgp-32    	  479968	      2487 ns/op	   0.40 MB/s	     848 B/op	      18 allocs/op

GOB:

Size: 1409 bytes

BenchmarkEncodeFileInfoGOB-32    	  333339	      3237 ns/op	   0.31 MB/s	     576 B/op	      19 allocs/op
BenchmarkDecodeFileInfoGOB-32    	   20869	     57837 ns/op	   0.02 MB/s	   16439 B/op	     428 allocs/op
```
This commit is contained in:
Klaus Post
2020-11-02 17:07:52 -08:00
committed by GitHub
parent 86e0d272f3
commit 37749f4623
8 changed files with 1777 additions and 41 deletions

View File

@@ -34,6 +34,7 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/rest"
xnet "github.com/minio/minio/pkg/net"
"github.com/tinylib/msgp/msgp"
)
func isNetworkError(err error) bool {
@@ -290,7 +291,7 @@ func (client *storageRESTClient) WriteMetadata(ctx context.Context, volume, path
values.Set(storageRESTFilePath, path)
var reader bytes.Buffer
if err := gob.NewEncoder(&reader).Encode(fi); err != nil {
if err := msgp.Encode(&reader, &fi); err != nil {
return err
}
@@ -305,7 +306,7 @@ func (client *storageRESTClient) DeleteVersion(ctx context.Context, volume, path
values.Set(storageRESTFilePath, path)
var buffer bytes.Buffer
if err := gob.NewEncoder(&buffer).Encode(fi); err != nil {
if err := msgp.Encode(&buffer, &fi); err != nil {
return err
}
@@ -341,7 +342,7 @@ func (client *storageRESTClient) CheckParts(ctx context.Context, volume string,
values.Set(storageRESTFilePath, path)
var reader bytes.Buffer
if err := gob.NewEncoder(&reader).Encode(fi); err != nil {
if err := msgp.Encode(&reader, &fi); err != nil {
logger.LogIf(context.Background(), err)
return err
}
@@ -377,8 +378,7 @@ func (client *storageRESTClient) ReadVersion(ctx context.Context, volume, path,
return fi, err
}
defer http.DrainBody(respBody)
err = gob.NewDecoder(respBody).Decode(&fi)
err = msgp.Decode(respBody, &fi)
return fi, err
}
@@ -447,10 +447,10 @@ func (client *storageRESTClient) WalkSplunk(ctx context.Context, volume, dirPath
defer close(ch)
defer http.DrainBody(respBody)
decoder := gob.NewDecoder(respBody)
decoder := msgp.NewReader(respBody)
for {
var fi FileInfo
if gerr := decoder.Decode(&fi); gerr != nil {
if gerr := fi.DecodeMsg(decoder); gerr != nil {
// Upon error return
return
}
@@ -482,12 +482,12 @@ func (client *storageRESTClient) WalkVersions(ctx context.Context, volume, dirPa
defer close(ch)
defer http.DrainBody(respBody)
decoder := gob.NewDecoder(respBody)
decoder := msgp.NewReader(respBody)
for {
var fi FileInfoVersions
if gerr := decoder.Decode(&fi); gerr != nil {
if gerr := fi.DecodeMsg(decoder); gerr != nil {
// Upon error return
if gerr != io.EOF {
if msgp.Cause(gerr) != io.EOF {
logger.LogIf(GlobalContext, gerr)
}
return
@@ -519,10 +519,10 @@ func (client *storageRESTClient) Walk(ctx context.Context, volume, dirPath, mark
defer close(ch)
defer http.DrainBody(respBody)
decoder := gob.NewDecoder(respBody)
decoder := msgp.NewReader(respBody)
for {
var fi FileInfo
if gerr := decoder.Decode(&fi); gerr != nil {
if gerr := fi.DecodeMsg(decoder); gerr != nil {
// Upon error return
return
}
@@ -575,10 +575,11 @@ func (client *storageRESTClient) DeleteVersions(ctx context.Context, volume stri
values.Set(storageRESTTotalVersions, strconv.Itoa(len(versions)))
var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)
encoder := msgp.NewWriter(&buffer)
for _, version := range versions {
encoder.Encode(&version)
version.EncodeMsg(encoder)
}
logger.LogIf(ctx, encoder.Flush())
errs = make([]error, len(versions))
@@ -632,7 +633,7 @@ func (client *storageRESTClient) VerifyFile(ctx context.Context, volume, path st
values.Set(storageRESTFilePath, path)
var reader bytes.Buffer
if err := gob.NewEncoder(&reader).Encode(fi); err != nil {
if err := msgp.Encode(&reader, &fi); err != nil {
return err
}