Browse Source

Don't load block list in ...Truncated methods

Speeds up and reduces allocations on those operations, at the price of
having a manually tweaked XDR decoder for FileInfoTruncated.

benchmark                         old ns/op      new ns/op      delta
BenchmarkReplaceAll-8             1868198122     1880206886     +0.64%
BenchmarkUpdateOneChanged-8       231852         172695         -25.51%
BenchmarkUpdateOneUnchanged-8     230624         179341         -22.24%
BenchmarkNeedHalf-8               104601744      109461427      +4.65%
BenchmarkHave-8                   29102480       34105026       +17.19%
BenchmarkGlobal-8                 150547687      172778045      +14.77%
BenchmarkNeedHalfTruncated-8      102471355      76564986       -25.28%
BenchmarkHaveTruncated-8          28758368       14277481       -50.35%
BenchmarkGlobalTruncated-8        151192913      106070136      -29.84%

benchmark                         old allocs     new allocs     delta
BenchmarkReplaceAll-8             555577         557554         +0.36%
BenchmarkUpdateOneChanged-8       1135           587            -48.28%
BenchmarkUpdateOneUnchanged-8     1135           587            -48.28%
BenchmarkNeedHalf-8               374780         374775         -0.00%
BenchmarkHave-8                   151992         152085         +0.06%
BenchmarkGlobal-8                 530033         530135         +0.02%
BenchmarkNeedHalfTruncated-8      374699         22160          -94.09%
BenchmarkHaveTruncated-8          151834         4904           -96.77%
BenchmarkGlobalTruncated-8        530037         30536          -94.24%

benchmark                         old bytes      new bytes      delta
BenchmarkReplaceAll-8             1765116216     1765305376     +0.01%
BenchmarkUpdateOneChanged-8       135085         93043          -31.12%
BenchmarkUpdateOneUnchanged-8     134976         92928          -31.15%
BenchmarkNeedHalf-8               44758752       44751791       -0.02%
BenchmarkHave-8                   11845052       11967172       +1.03%
BenchmarkGlobal-8                 80431136       80431065       -0.00%
BenchmarkNeedHalfTruncated-8      46526459       18243543       -60.79%
BenchmarkHaveTruncated-8          11348357       418998         -96.31%
BenchmarkGlobalTruncated-8        80977672       43116991       -46.75%
Jakob Borg 10 years ago
parent
commit
83131103cf
2 changed files with 35 additions and 9 deletions
  1. 31 9
      lib/db/truncated.go
  2. 4 0
      lib/protocol/message.go

+ 31 - 9
lib/db/truncated.go

@@ -6,22 +6,44 @@
 
 package db
 
-import "github.com/syncthing/syncthing/lib/protocol"
+import (
+	"bytes"
+
+	"github.com/calmh/xdr"
+	"github.com/syncthing/syncthing/lib/protocol"
+)
 
 type FileInfoTruncated struct {
 	protocol.FileInfo
-	ActualSize int64
 }
 
-func (f *FileInfoTruncated) UnmarshalXDR(bs []byte) error {
-	err := f.FileInfo.UnmarshalXDR(bs)
-	f.ActualSize = f.FileInfo.Size()
-	f.FileInfo.Blocks = nil
-	return err
+func (o *FileInfoTruncated) UnmarshalXDR(bs []byte) error {
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (f FileInfoTruncated) Size() int64 {
-	return f.ActualSize
+func (o *FileInfoTruncated) DecodeXDRFrom(xr *xdr.Reader) error {
+	o.Name = xr.ReadStringMax(8192)
+	o.Flags = xr.ReadUint32()
+	o.Modified = int64(xr.ReadUint64())
+	(&o.Version).DecodeXDRFrom(xr)
+	o.LocalVersion = int64(xr.ReadUint64())
+	_BlocksSize := int(xr.ReadUint32())
+	if _BlocksSize < 0 {
+		return xdr.ElementSizeExceeded("Blocks", _BlocksSize, 1000000)
+	}
+	if _BlocksSize > 1000000 {
+		return xdr.ElementSizeExceeded("Blocks", _BlocksSize, 1000000)
+	}
+
+	buf := make([]byte, 64)
+	for i := 0; i < _BlocksSize; i++ {
+		size := xr.ReadUint32()
+		o.CachedSize += int64(size)
+		xr.ReadBytesMaxInto(64, buf)
+	}
+	return xr.Error()
 }
 
 func BlocksToSize(num int) int64 {

+ 4 - 0
lib/protocol/message.go

@@ -33,9 +33,13 @@ func (f FileInfo) Size() (bytes int64) {
 	if f.IsDeleted() || f.IsDirectory() {
 		return 128
 	}
+	if f.CachedSize > 0 {
+		return f.CachedSize
+	}
 	for _, b := range f.Blocks {
 		bytes += int64(b.Size)
 	}
+	f.CachedSize = bytes
 	return
 }