From 1eeddfa291ecbeb1ef0283bf51718763ac9e58ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 23 Oct 2017 14:06:16 +0200 Subject: [PATCH] Some perf work This takes off some time in our benchmark, but we still spend a lot of time creating the filenames out of the slice and allocating objects. --- managed_tree.go | 33 ++++++++++++++++++++------------- tree.go | 4 ++-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/managed_tree.go b/managed_tree.go index cc509a7..8aadb17 100644 --- a/managed_tree.go +++ b/managed_tree.go @@ -12,13 +12,13 @@ import ( // Tree. type ManagedTree struct { m map[string]*TreeEntry - l []*TreeEntry + l []TreeEntry } func (t *ManagedTree) EntryById(id *Oid) *TreeEntry { for _, entry := range t.l { if entry.Id.Equal(id) { - return entry + return &entry } } @@ -30,7 +30,7 @@ func (t *ManagedTree) EntryByName(filename string) *TreeEntry { } func (t *ManagedTree) EntryByIndex(index uint64) *TreeEntry { - return t.l[index] + return &t.l[index] } func (t *ManagedTree) EntryCount() uint64 { @@ -54,8 +54,12 @@ func NewManagedTree(r *Repository, id *Oid) (*ManagedTree, error) { } data := obj.Data() - l := make([]*TreeEntry, 0, 8) - m := make(map[string]*TreeEntry) + // var buf bytes.Buffer + // buf.Grow(len(borrowedData)) + // buf.Write(borrowedData) + // data := buf.Bytes() + + l := make([]TreeEntry, 0, 24) var done bool for !done { @@ -74,27 +78,30 @@ func NewManagedTree(r *Repository, id *Oid) (*ManagedTree, error) { return nil, errors.New("failed to find NUL after filename") } - var name bytes.Buffer - name.Grow(nulAt) - name.Write(data[:nulAt]) + name := string(data[:nulAt]) data = data[nulAt+1:] - oid := NewOidFromBytes(data) + oid := data[:20] if len(data) > 20 { data = data[20:] } else { done = true } - entry := &TreeEntry{ - Name: name.String(), - Id: oid, + entry := TreeEntry{ + Name: name, + //Id: Oid(oid), Type: typeFromMode(mode), Filemode: Filemode(mode), } + copy(entry.Id[:], oid) l = append(l, entry) - m[entry.Name] = entry + } + + m := make(map[string]*TreeEntry, len(l)) + for _, entry := range l { + m[entry.Name] = &entry } // This avoids the runtime from garbage-collecting 'obj' and freeing the diff --git a/tree.go b/tree.go index ee14ec5..4a62159 100644 --- a/tree.go +++ b/tree.go @@ -33,7 +33,7 @@ func (t *Tree) AsObject() *Object { type TreeEntry struct { Name string - Id *Oid + Id Oid Type ObjectType Filemode Filemode } @@ -41,7 +41,7 @@ type TreeEntry struct { func newTreeEntry(entry *C.git_tree_entry) *TreeEntry { return &TreeEntry{ C.GoString(C.git_tree_entry_name(entry)), - newOidFromC(C.git_tree_entry_id(entry)), + *newOidFromC(C.git_tree_entry_id(entry)), ObjectType(C.git_tree_entry_type(entry)), Filemode(C.git_tree_entry_filemode(entry)), }