diff options
author | Miguel Molina <miguel@erizocosmi.co> | 2017-09-06 12:13:41 +0200 |
---|---|---|
committer | Miguel Molina <miguel@erizocosmi.co> | 2017-09-06 12:13:41 +0200 |
commit | 0b68b0fd8e8a0f57419a72479ddeb8d267f15f72 (patch) | |
tree | a6b49669163d3a0a1c85141513eeb52c3ee6561e /plumbing | |
parent | 2dc59a6925f47e9d1bc99dd64d86e37b79b65d11 (diff) | |
download | go-git-0b68b0fd8e8a0f57419a72479ddeb8d267f15f72.tar.gz |
packfile: reuse delta indexes when possible
Signed-off-by: Miguel Molina <miguel@erizocosmi.co>
Diffstat (limited to 'plumbing')
-rw-r--r-- | plumbing/format/packfile/delta_selector.go | 11 | ||||
-rw-r--r-- | plumbing/format/packfile/delta_test.go | 4 | ||||
-rw-r--r-- | plumbing/format/packfile/diff_delta.go | 17 |
3 files changed, 22 insertions, 10 deletions
diff --git a/plumbing/format/packfile/delta_selector.go b/plumbing/format/packfile/delta_selector.go index cc0ae0f..78b5733 100644 --- a/plumbing/format/packfile/delta_selector.go +++ b/plumbing/format/packfile/delta_selector.go @@ -172,6 +172,7 @@ func (dw *deltaSelector) sort(objectsToPack []*ObjectToPack) { } func (dw *deltaSelector) walk(objectsToPack []*ObjectToPack) error { + indexMap := make(map[plumbing.Hash]deltaIndex) for i := 0; i < len(objectsToPack); i++ { target := objectsToPack[i] @@ -196,7 +197,7 @@ func (dw *deltaSelector) walk(objectsToPack []*ObjectToPack) error { break } - if err := dw.tryToDeltify(base, target); err != nil { + if err := dw.tryToDeltify(indexMap, base, target); err != nil { return err } } @@ -205,7 +206,7 @@ func (dw *deltaSelector) walk(objectsToPack []*ObjectToPack) error { return nil } -func (dw *deltaSelector) tryToDeltify(base, target *ObjectToPack) error { +func (dw *deltaSelector) tryToDeltify(indexMap map[plumbing.Hash]deltaIndex, base, target *ObjectToPack) error { // If the sizes are radically different, this is a bad pairing. if target.Size() < base.Size()>>4 { return nil @@ -238,8 +239,12 @@ func (dw *deltaSelector) tryToDeltify(base, target *ObjectToPack) error { return err } + if _, ok := indexMap[base.Hash()]; !ok { + indexMap[base.Hash()] = make(deltaIndex) + } + // Now we can generate the delta using originals - delta, err := GetDelta(base.Original, target.Original) + delta, err := getDelta(indexMap[base.Hash()], base.Original, target.Original) if err != nil { return err } diff --git a/plumbing/format/packfile/delta_test.go b/plumbing/format/packfile/delta_test.go index 42b777a..f6e93d2 100644 --- a/plumbing/format/packfile/delta_test.go +++ b/plumbing/format/packfile/delta_test.go @@ -84,7 +84,7 @@ func (s *DeltaSuite) TestAddDelta(c *C) { for _, t := range s.testCases { baseBuf := genBytes(t.base) targetBuf := genBytes(t.target) - delta := DiffDelta(baseBuf, targetBuf) + delta := DiffDelta(make(deltaIndex), baseBuf, targetBuf) result, err := PatchDelta(baseBuf, delta) c.Log("Executing test case:", t.description) @@ -98,7 +98,7 @@ func (s *DeltaSuite) TestIncompleteDelta(c *C) { c.Log("Incomplete delta on:", t.description) baseBuf := genBytes(t.base) targetBuf := genBytes(t.target) - delta := DiffDelta(baseBuf, targetBuf) + delta := DiffDelta(make(deltaIndex), baseBuf, targetBuf) delta = delta[:len(delta)-2] result, err := PatchDelta(baseBuf, delta) c.Assert(err, NotNil) diff --git a/plumbing/format/packfile/diff_delta.go b/plumbing/format/packfile/diff_delta.go index 7e9f822..d0db46b 100644 --- a/plumbing/format/packfile/diff_delta.go +++ b/plumbing/format/packfile/diff_delta.go @@ -26,6 +26,10 @@ const ( // To generate target again, you will need the obtained object and "base" one. // Error will be returned if base or target object cannot be read. func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) { + return getDelta(make(deltaIndex), base, target) +} + +func getDelta(index deltaIndex, base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) { br, err := base.Reader() if err != nil { return nil, err @@ -45,7 +49,7 @@ func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, erro return nil, err } - db := DiffDelta(bb, tb) + db := DiffDelta(index, bb, tb) delta := &plumbing.MemoryObject{} _, err = delta.Write(db) if err != nil { @@ -59,13 +63,15 @@ func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, erro } // DiffDelta returns the delta that transforms src into tgt. -func DiffDelta(src []byte, tgt []byte) []byte { +func DiffDelta(sindex deltaIndex, src []byte, tgt []byte) []byte { buf := bufPool.Get().(*bytes.Buffer) buf.Reset() buf.Write(deltaEncodeSize(len(src))) buf.Write(deltaEncodeSize(len(tgt))) - sindex := initMatch(src) + if len(sindex) == 0 { + initMatch(sindex, src) + } ibuf := bufPool.Get().(*bytes.Buffer) ibuf.Reset() @@ -126,9 +132,8 @@ func encodeInsertOperation(ibuf, buf *bytes.Buffer) { ibuf.Reset() } -func initMatch(src []byte) map[uint32]int { +func initMatch(index map[uint32]int, src []byte) map[uint32]int { i := 0 - index := make(map[uint32]int) for { if i+s > len(src) { break @@ -213,3 +218,5 @@ func encodeCopyOperation(offset, length int) []byte { return append([]byte{byte(code)}, opcodes...) } + +type deltaIndex map[uint32]int |