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

Commit 8beb3ee

Browse files
orisanomcuadros
authored andcommitted
Worktree: improve build index performance. (#1179)
1 parent c363771 commit 8beb3ee

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

repository_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"golang.org/x/crypto/openpgp"
1717
"golang.org/x/crypto/openpgp/armor"
1818
openpgperr "golang.org/x/crypto/openpgp/errors"
19+
1920
"gopkg.in/src-d/go-git.v4/config"
2021
"gopkg.in/src-d/go-git.v4/plumbing"
2122
"gopkg.in/src-d/go-git.v4/plumbing/cache"
@@ -2671,3 +2672,22 @@ func BenchmarkObjects(b *testing.B) {
26712672
})
26722673
}
26732674
}
2675+
2676+
func BenchmarkPlainClone(b *testing.B) {
2677+
for i := 0; i < b.N; i++ {
2678+
t, err := ioutil.TempDir("", "")
2679+
if err != nil {
2680+
b.Fatal(err)
2681+
}
2682+
_, err = PlainClone(t, false, &CloneOptions{
2683+
URL: "https://github.com/knqyf263/vuln-list",
2684+
Depth: 1,
2685+
})
2686+
if err != nil {
2687+
b.Error(err)
2688+
}
2689+
b.StopTimer()
2690+
os.RemoveAll(t)
2691+
b.StartTimer()
2692+
}
2693+
}

storage/filesystem/index.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ func (s *IndexStorage) SetIndex(idx *index.Index) (err error) {
2020
}
2121

2222
defer ioutil.CheckClose(f, &err)
23+
bw := bufio.NewWriter(f)
24+
defer func() {
25+
if e := bw.Flush(); err == nil && e != nil {
26+
err = e
27+
}
28+
}()
2329

24-
e := index.NewEncoder(f)
30+
e := index.NewEncoder(bw)
2531
err = e.Encode(idx)
2632
return err
2733
}

worktree.go

+56-17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"path/filepath"
1111
"strings"
12+
"sync"
1213

1314
"gopkg.in/src-d/go-git.v4/config"
1415
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -304,6 +305,7 @@ func (w *Worktree) resetIndex(t *object.Tree) error {
304305
if err != nil {
305306
return err
306307
}
308+
b := newIndexBuilder(idx)
307309

308310
changes, err := w.diffTreeWithStaging(t, true)
309311
if err != nil {
@@ -330,19 +332,20 @@ func (w *Worktree) resetIndex(t *object.Tree) error {
330332
name = ch.From.String()
331333
}
332334

333-
_, _ = idx.Remove(name)
335+
b.Remove(name)
334336
if e == nil {
335337
continue
336338
}
337339

338-
idx.Entries = append(idx.Entries, &index.Entry{
340+
b.Add(&index.Entry{
339341
Name: name,
340342
Hash: e.Hash,
341343
Mode: e.Mode,
342344
})
343345

344346
}
345347

348+
b.Write(idx)
346349
return w.r.Storer.SetIndex(idx)
347350
}
348351

@@ -356,17 +359,19 @@ func (w *Worktree) resetWorktree(t *object.Tree) error {
356359
if err != nil {
357360
return err
358361
}
362+
b := newIndexBuilder(idx)
359363

360364
for _, ch := range changes {
361-
if err := w.checkoutChange(ch, t, idx); err != nil {
365+
if err := w.checkoutChange(ch, t, b); err != nil {
362366
return err
363367
}
364368
}
365369

370+
b.Write(idx)
366371
return w.r.Storer.SetIndex(idx)
367372
}
368373

369-
func (w *Worktree) checkoutChange(ch merkletrie.Change, t *object.Tree, idx *index.Index) error {
374+
func (w *Worktree) checkoutChange(ch merkletrie.Change, t *object.Tree, idx *indexBuilder) error {
370375
a, err := ch.Action()
371376
if err != nil {
372377
return err
@@ -445,7 +450,7 @@ func (w *Worktree) setHEADCommit(commit plumbing.Hash) error {
445450
func (w *Worktree) checkoutChangeSubmodule(name string,
446451
a merkletrie.Action,
447452
e *object.TreeEntry,
448-
idx *index.Index,
453+
idx *indexBuilder,
449454
) error {
450455
switch a {
451456
case merkletrie.Modify:
@@ -479,11 +484,11 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
479484
a merkletrie.Action,
480485
t *object.Tree,
481486
e *object.TreeEntry,
482-
idx *index.Index,
487+
idx *indexBuilder,
483488
) error {
484489
switch a {
485490
case merkletrie.Modify:
486-
_, _ = idx.Remove(name)
491+
idx.Remove(name)
487492

488493
// to apply perm changes the file is deleted, billy doesn't implement
489494
// chmod
@@ -508,6 +513,12 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
508513
return nil
509514
}
510515

516+
var copyBufferPool = sync.Pool{
517+
New: func() interface{} {
518+
return make([]byte, 32*1024)
519+
},
520+
}
521+
511522
func (w *Worktree) checkoutFile(f *object.File) (err error) {
512523
mode, err := f.Mode.ToOSFileMode()
513524
if err != nil {
@@ -531,8 +542,9 @@ func (w *Worktree) checkoutFile(f *object.File) (err error) {
531542
}
532543

533544
defer ioutil.CheckClose(to, &err)
534-
535-
_, err = io.Copy(to, from)
545+
buf := copyBufferPool.Get().([]byte)
546+
_, err = io.CopyBuffer(to, from, buf)
547+
copyBufferPool.Put(buf)
536548
return
537549
}
538550

@@ -569,19 +581,18 @@ func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) {
569581
return
570582
}
571583

572-
func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *index.Index) error {
573-
_, _ = idx.Remove(name)
574-
idx.Entries = append(idx.Entries, &index.Entry{
584+
func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *indexBuilder) error {
585+
idx.Remove(name)
586+
idx.Add(&index.Entry{
575587
Hash: f.Hash,
576588
Name: name,
577589
Mode: filemode.Submodule,
578590
})
579-
580591
return nil
581592
}
582593

583-
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *index.Index) error {
584-
_, _ = idx.Remove(name)
594+
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *indexBuilder) error {
595+
idx.Remove(name)
585596
fi, err := w.Filesystem.Lstat(name)
586597
if err != nil {
587598
return err
@@ -605,8 +616,7 @@ func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *index.Ind
605616
if fillSystemInfo != nil {
606617
fillSystemInfo(e, fi.Sys())
607618
}
608-
609-
idx.Entries = append(idx.Entries, e)
619+
idx.Add(e)
610620
return nil
611621
}
612622

@@ -913,3 +923,32 @@ func doCleanDirectories(fs billy.Filesystem, dir string) error {
913923
}
914924
return nil
915925
}
926+
927+
type indexBuilder struct {
928+
entries map[string]*index.Entry
929+
}
930+
931+
func newIndexBuilder(idx *index.Index) *indexBuilder {
932+
entries := make(map[string]*index.Entry, len(idx.Entries))
933+
for _, e := range idx.Entries {
934+
entries[e.Name] = e
935+
}
936+
return &indexBuilder{
937+
entries: entries,
938+
}
939+
}
940+
941+
func (b *indexBuilder) Write(idx *index.Index) {
942+
idx.Entries = idx.Entries[:0]
943+
for _, e := range b.entries {
944+
idx.Entries = append(idx.Entries, e)
945+
}
946+
}
947+
948+
func (b *indexBuilder) Add(e *index.Entry) {
949+
b.entries[e.Name] = e
950+
}
951+
952+
func (b *indexBuilder) Remove(name string) {
953+
delete(b.entries, filepath.ToSlash(name))
954+
}

0 commit comments

Comments
 (0)