Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 936f65d

Browse files
committed
plumbing: TreeWalker performance improvement, bufio pool for objects
Removes path.Clean and path.Join, as they're expensive in comparison to basic string manipulation that can be used here. Adds bufio.Buffer pool to be used by tag, tree and commit object decoding. Signed-off-by: Arran Walker <[email protected]>
1 parent e5268e9 commit 936f65d

File tree

4 files changed

+34
-9
lines changed

4 files changed

+34
-9
lines changed

plumbing/object/commit.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
171171
}
172172
defer ioutil.CheckClose(reader, &err)
173173

174-
r := bufio.NewReader(reader)
174+
r := bufPool.Get().(*bufio.Reader)
175+
defer bufPool.Put(r)
176+
r.Reset(reader)
175177

176178
var message bool
177179
var pgpsig bool

plumbing/object/common.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package object
2+
3+
import (
4+
"bufio"
5+
"sync"
6+
)
7+
8+
var bufPool = sync.Pool{
9+
New: func() interface{} {
10+
return bufio.NewReader(nil)
11+
},
12+
}

plumbing/object/tag.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ func (t *Tag) Decode(o plumbing.EncodedObject) (err error) {
9393
}
9494
defer ioutil.CheckClose(reader, &err)
9595

96-
r := bufio.NewReader(reader)
96+
r := bufPool.Get().(*bufio.Reader)
97+
defer bufPool.Put(r)
98+
r.Reset(reader)
9799
for {
98100
var line []byte
99101
line, err = r.ReadBytes('\n')

plumbing/object/tree.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
230230
}
231231
defer ioutil.CheckClose(reader, &err)
232232

233-
r := bufio.NewReader(reader)
233+
r := bufPool.Get().(*bufio.Reader)
234+
defer bufPool.Put(r)
235+
r.Reset(reader)
234236
for {
235237
str, err := r.ReadString(' ')
236238
if err != nil {
@@ -383,7 +385,7 @@ func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWa
383385
// underlying repository will be skipped automatically. It is possible that this
384386
// may change in future versions.
385387
func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
386-
var obj Object
388+
var obj *Tree
387389
for {
388390
current := len(w.stack) - 1
389391
if current < 0 {
@@ -403,7 +405,7 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
403405
// Finished with the current tree, move back up to the parent
404406
w.stack = w.stack[:current]
405407
w.base, _ = path.Split(w.base)
406-
w.base = path.Clean(w.base) // Remove trailing slash
408+
w.base = strings.TrimSuffix(w.base, "/")
407409
continue
408410
}
409411

@@ -419,7 +421,7 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
419421
obj, err = GetTree(w.s, entry.Hash)
420422
}
421423

422-
name = path.Join(w.base, entry.Name)
424+
name = simpleJoin(w.base, entry.Name)
423425

424426
if err != nil {
425427
err = io.EOF
@@ -433,9 +435,9 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
433435
return
434436
}
435437

436-
if t, ok := obj.(*Tree); ok {
437-
w.stack = append(w.stack, &treeEntryIter{t, 0})
438-
w.base = path.Join(w.base, entry.Name)
438+
if obj != nil {
439+
w.stack = append(w.stack, &treeEntryIter{obj, 0})
440+
w.base = simpleJoin(w.base, entry.Name)
439441
}
440442

441443
return
@@ -509,3 +511,10 @@ func (iter *TreeIter) ForEach(cb func(*Tree) error) error {
509511
return cb(t)
510512
})
511513
}
514+
515+
func simpleJoin(parent, child string) string {
516+
if len(parent) > 0 {
517+
return parent + "/" + child
518+
}
519+
return child
520+
}

0 commit comments

Comments
 (0)