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

Commit ecda5c1

Browse files
authored
Merge pull request #769 from dennwc/optimize-1
storage/filesystem: optimize packfile iterator
2 parents 43fe660 + fa6b152 commit ecda5c1

File tree

1 file changed

+61
-22
lines changed

1 file changed

+61
-22
lines changed

storage/filesystem/object.go

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.Encode
365365
return nil, err
366366
}
367367

368-
seen := make(map[plumbing.Hash]bool)
368+
seen := make(map[plumbing.Hash]struct{})
369369
var iters []storer.EncodedObjectIter
370370
if len(objects) != 0 {
371371
iters = append(iters, &objectsIter{s: s, t: t, h: objects})
@@ -377,11 +377,11 @@ func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.Encode
377377
return nil, err
378378
}
379379

380-
iters = append(iters, packi...)
380+
iters = append(iters, packi)
381381
return storer.NewMultiEncodedObjectIter(iters), nil
382382
}
383383

384-
func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumbing.Hash]bool) ([]storer.EncodedObjectIter, error) {
384+
func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumbing.Hash]struct{}) (storer.EncodedObjectIter, error) {
385385
if err := s.requireIndex(); err != nil {
386386
return nil, err
387387
}
@@ -390,40 +390,80 @@ func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumb
390390
if err != nil {
391391
return nil, err
392392
}
393+
return &lazyPackfilesIter{
394+
hashes: packs,
395+
open: func(h plumbing.Hash) (storer.EncodedObjectIter, error) {
396+
pack, err := s.dir.ObjectPack(h)
397+
if err != nil {
398+
return nil, err
399+
}
400+
return newPackfileIter(pack, t, seen, s.index[h], s.deltaBaseCache)
401+
},
402+
}, nil
403+
}
393404

394-
var iters []storer.EncodedObjectIter
395-
for _, h := range packs {
396-
pack, err := s.dir.ObjectPack(h)
397-
if err != nil {
398-
return nil, err
399-
}
405+
type lazyPackfilesIter struct {
406+
hashes []plumbing.Hash
407+
open func(h plumbing.Hash) (storer.EncodedObjectIter, error)
408+
cur storer.EncodedObjectIter
409+
}
400410

401-
iter, err := newPackfileIter(pack, t, seen, s.index[h], s.deltaBaseCache)
402-
if err != nil {
411+
func (it *lazyPackfilesIter) Next() (plumbing.EncodedObject, error) {
412+
for {
413+
if it.cur == nil {
414+
if len(it.hashes) == 0 {
415+
return nil, io.EOF
416+
}
417+
h := it.hashes[0]
418+
it.hashes = it.hashes[1:]
419+
420+
sub, err := it.open(h)
421+
if err == io.EOF {
422+
continue
423+
} else if err != nil {
424+
return nil, err
425+
}
426+
it.cur = sub
427+
}
428+
ob, err := it.cur.Next()
429+
if err == io.EOF {
430+
it.cur.Close()
431+
it.cur = nil
432+
continue
433+
} else if err != nil {
403434
return nil, err
404435
}
405-
406-
iters = append(iters, iter)
436+
return ob, nil
407437
}
438+
}
408439

409-
return iters, nil
440+
func (it *lazyPackfilesIter) ForEach(cb func(plumbing.EncodedObject) error) error {
441+
return storer.ForEachIterator(it, cb)
442+
}
443+
444+
func (it *lazyPackfilesIter) Close() {
445+
if it.cur != nil {
446+
it.cur.Close()
447+
it.cur = nil
448+
}
449+
it.hashes = nil
410450
}
411451

412452
type packfileIter struct {
413453
f billy.File
414454
d *packfile.Decoder
415455
t plumbing.ObjectType
416456

417-
seen map[plumbing.Hash]bool
457+
seen map[plumbing.Hash]struct{}
418458
position uint32
419459
total uint32
420460
}
421461

422462
func NewPackfileIter(f billy.File, t plumbing.ObjectType) (storer.EncodedObjectIter, error) {
423-
return newPackfileIter(f, t, make(map[plumbing.Hash]bool), nil, nil)
463+
return newPackfileIter(f, t, make(map[plumbing.Hash]struct{}), nil, nil)
424464
}
425465

426-
func newPackfileIter(f billy.File, t plumbing.ObjectType, seen map[plumbing.Hash]bool,
466+
func newPackfileIter(f billy.File, t plumbing.ObjectType, seen map[plumbing.Hash]struct{},
427467
index *packfile.Index, cache cache.Object) (storer.EncodedObjectIter, error) {
428468
s := packfile.NewScanner(f)
429469
_, total, err := s.Header()
@@ -464,7 +504,7 @@ func (iter *packfileIter) Next() (plumbing.EncodedObject, error) {
464504
continue
465505
}
466506

467-
if iter.seen[obj.Hash()] {
507+
if _, ok := iter.seen[obj.Hash()]; ok {
468508
return iter.Next()
469509
}
470510

@@ -516,12 +556,11 @@ func (iter *objectsIter) Close() {
516556
iter.h = []plumbing.Hash{}
517557
}
518558

519-
func hashListAsMap(l []plumbing.Hash) map[plumbing.Hash]bool {
520-
m := make(map[plumbing.Hash]bool, len(l))
559+
func hashListAsMap(l []plumbing.Hash) map[plumbing.Hash]struct{} {
560+
m := make(map[plumbing.Hash]struct{}, len(l))
521561
for _, h := range l {
522-
m[h] = true
562+
m[h] = struct{}{}
523563
}
524-
525564
return m
526565
}
527566

0 commit comments

Comments
 (0)