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

Commit 2efbdaa

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 <arran.walker@fiveturns.org>
1 parent e5268e9 commit 2efbdaa

File tree

4 files changed

+35
-9
lines changed

4 files changed

+35
-9
lines changed

plumbing/object/commit.go

+3-1
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

+12
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

+3-1
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

+17-7
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,11 @@ 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+
if len(w.base) > 0 {
425+
name = w.base + "/" + entry.Name
426+
} else {
427+
name = entry.Name
428+
}
423429

424430
if err != nil {
425431
err = io.EOF
@@ -433,9 +439,13 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
433439
return
434440
}
435441

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)
442+
if obj != nil {
443+
w.stack = append(w.stack, &treeEntryIter{obj, 0})
444+
if len(w.base) > 0 {
445+
w.base = w.base + "/" + entry.Name
446+
} else {
447+
w.base = entry.Name
448+
}
439449
}
440450

441451
return

0 commit comments

Comments
 (0)