Optimize pack readHeader() implementation

Load pack header length and 15 header entries with single backend
request. This eliminates separate header Load() request for most pack
files and significantly improves index.New() performance.

Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
This commit is contained in:
Igor Fedorenko committed 2018-01-23 22:02:25 -05:00
1 parent b63de7c798
commit 953f3d55ee
3 files changed
+88 -26

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
package pack
import (
"bytes"
"encoding/binary"
"io"
"testing"
"github.com/restic/restic/internal/crypto"
rtest "github.com/restic/restic/internal/test"
)
type countingReaderAt struct {
delegate io.ReaderAt
invocationCount int
}
func (rd *countingReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
rd.invocationCount++
return rd.delegate.ReadAt(p, off)
}
func TestReadHeaderEagerLoad(t *testing.T) {
testReadHeader := func(entryCount uint, expectedReadInvocationCount int) {
expectedHeader := rtest.Random(0, int(entryCount*entrySize)+crypto.Extension)
buf := &bytes.Buffer{}
buf.Write(rtest.Random(0, 100)) // pack blobs data
buf.Write(expectedHeader) // pack header
binary.Write(buf, binary.LittleEndian, uint32(len(expectedHeader))) // pack header length
rd := &countingReaderAt{delegate: bytes.NewReader(buf.Bytes())}
header, err := readHeader(rd, int64(buf.Len()))
rtest.OK(t, err)
rtest.Equals(t, expectedHeader, header)
rtest.Equals(t, expectedReadInvocationCount, rd.invocationCount)
}
testReadHeader(1, 1)
testReadHeader(eagerEntries-1, 1)
testReadHeader(eagerEntries, 1)
testReadHeader(eagerEntries+1, 2)
}