Skip to content

Commit 42fde01

Browse files
committed
perf: improve the way we check if refs are not pointing to commits
Fixes #775 Fixes #777 Before, each time we got a new reference, we were checking if it pointed to a commit. This incurred in a performance penalty and an increase of 2x in memory usage and 4x in allocations, as more objects were being read from the repository. Instead, now we use the already present resolveCommit to check it the moment we get the object, since we have to get it anyway. This way, we have the exact same behaviour without having any performance penalty or memory usage increase. Signed-off-by: Miguel Molina <[email protected]>
1 parent e1f8b1d commit 42fde01

File tree

5 files changed

+38
-93
lines changed

5 files changed

+38
-93
lines changed

commits.go

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -229,46 +229,50 @@ func (i *commitIter) loadNextRef() (err error) {
229229
return err
230230
}
231231

232-
ignored, err := isIgnoredReference(i.repo.Repository, i.ref)
233-
if err != nil {
234-
if i.skipGitErrors {
235-
continue
236-
}
237-
238-
return err
239-
}
240-
241-
if ignored {
232+
if isIgnoredReference(i.ref) {
242233
continue
243234
}
244235

245-
i.queue = append(i.queue, i.ref.Hash())
246-
247236
return nil
248237
}
249238
}
250239

251240
func (i *commitIter) Next() (*object.Commit, error) {
252241
for {
242+
var commit *object.Commit
243+
var err error
244+
253245
if i.ref == nil {
254246
if err := i.loadNextRef(); err != nil {
255247
return nil, err
256248
}
257-
}
258249

259-
if len(i.queue) == 0 {
260-
i.ref = nil
261-
continue
262-
}
250+
if _, ok := i.seen[i.ref.Hash()]; ok {
251+
continue
252+
}
253+
i.seen[i.ref.Hash()] = struct{}{}
263254

264-
hash := i.queue[0]
265-
i.queue = i.queue[1:]
266-
if _, ok := i.seen[hash]; ok {
267-
continue
255+
commit, err = resolveCommit(i.repo, i.ref.Hash())
256+
if errInvalidCommit.Is(err) {
257+
i.ref = nil
258+
continue
259+
}
260+
} else {
261+
if len(i.queue) == 0 {
262+
i.ref = nil
263+
continue
264+
}
265+
266+
hash := i.queue[0]
267+
i.queue = i.queue[1:]
268+
if _, ok := i.seen[hash]; ok {
269+
continue
270+
}
271+
i.seen[hash] = struct{}{}
272+
273+
commit, err = i.repo.CommitObject(hash)
268274
}
269-
i.seen[hash] = struct{}{}
270275

271-
commit, err := i.repo.CommitObject(hash)
272276
if err != nil {
273277
if i.skipGitErrors {
274278
continue

integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ func TestMissingHeadRefs(t *testing.T) {
594594

595595
rows, err := sql.RowIterToRows(iter)
596596
require.NoError(err)
597-
require.Len(rows, 54)
597+
require.Len(rows, 56)
598598
}
599599

600600
func BenchmarkQueries(b *testing.B) {

ref_commits.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -305,32 +305,19 @@ func (i *refCommitsRowIter) next() (sql.Row, error) {
305305
i.repo.Close()
306306
return nil, err
307307
}
308-
309-
ignored, err := isIgnoredReference(i.repo.Repository, ref)
310-
if err != nil {
311-
if i.skipGitErrors {
312-
continue
313-
}
314-
315-
return nil, err
316-
}
317-
318-
if ignored {
319-
continue
320-
}
321308
} else {
322309
ref = plumbing.NewHashReference(plumbing.ReferenceName("HEAD"), i.head.Hash())
323310
i.head = nil
324311
}
325312

326313
i.ref = ref
327-
if !i.shouldVisitRef(ref) {
314+
if !i.shouldVisitRef(ref) || isIgnoredReference(ref) {
328315
continue
329316
}
330317

331318
commit, err := resolveCommit(i.repo, ref.Hash())
332319
if err != nil {
333-
if i.skipGitErrors {
320+
if errInvalidCommit.Is(err) || i.skipGitErrors {
334321
continue
335322
}
336323

references.go

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"io"
77
"strings"
88

9-
git "gopkg.in/src-d/go-git.v4"
109
"gopkg.in/src-d/go-mysql-server.v0/sql"
1110

1211
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -300,16 +299,7 @@ func (i *refRowIter) next() (sql.Row, error) {
300299
return nil, err
301300
}
302301

303-
ignored, err := isIgnoredReference(i.repo.Repository, o)
304-
if err != nil {
305-
if i.skipGitErrors {
306-
continue
307-
}
308-
309-
return nil, err
310-
}
311-
312-
if ignored {
302+
if isIgnoredReference(o) {
313303
continue
314304
}
315305

@@ -351,15 +341,6 @@ func referenceToRow(repositoryID string, c *plumbing.Reference) sql.Row {
351341
)
352342
}
353343

354-
func isIgnoredReference(repo *git.Repository, ref *plumbing.Reference) (bool, error) {
355-
if ref.Type() != plumbing.HashReference {
356-
return true, nil
357-
}
358-
359-
obj, err := repo.Object(plumbing.AnyObject, ref.Hash())
360-
if err != nil {
361-
return false, err
362-
}
363-
364-
return obj.Type() != plumbing.CommitObject, nil
344+
func isIgnoredReference(r *plumbing.Reference) bool {
345+
return r.Type() != plumbing.HashReference
365346
}

squash_iterator.go

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -489,16 +489,7 @@ func (i *squashRefIter) Advance() error {
489489
}
490490
}
491491

492-
ignored, err := isIgnoredReference(i.repo.Repository, ref)
493-
if err != nil {
494-
if i.skipGitErrors {
495-
continue
496-
}
497-
498-
return err
499-
}
500-
501-
if ignored {
492+
if isIgnoredReference(ref) {
502493
continue
503494
}
504495

@@ -743,16 +734,7 @@ func (i *squashRepoRefsIter) Advance() error {
743734
}
744735
}
745736

746-
ignored, err := isIgnoredReference(i.repos.Repository().Repository, ref)
747-
if err != nil {
748-
if i.skipGitErrors {
749-
continue
750-
}
751-
752-
return err
753-
}
754-
755-
if ignored {
737+
if isIgnoredReference(ref) {
756738
continue
757739
}
758740

@@ -890,16 +872,7 @@ func (i *squashRemoteRefsIter) Advance() error {
890872
}
891873
}
892874

893-
ignored, err := isIgnoredReference(i.Repository().Repository, ref)
894-
if err != nil {
895-
if i.skipGitErrors {
896-
continue
897-
}
898-
899-
return err
900-
}
901-
902-
if ignored {
875+
if isIgnoredReference(ref) {
903876
continue
904877
}
905878

@@ -1010,7 +983,7 @@ func (i *squashRefRefCommitsIter) Advance() error {
1010983
"error": err,
1011984
}).Error("unable to get commit")
1012985

1013-
if i.skipGitErrors {
986+
if errInvalidCommit.Is(err) || i.skipGitErrors {
1014987
continue
1015988
}
1016989

@@ -1116,7 +1089,7 @@ func (i *squashRefHeadRefCommitsIter) Advance() error {
11161089
"error": err,
11171090
}).Error("unable to get commit")
11181091

1119-
if i.skipGitErrors {
1092+
if errInvalidCommit.Is(err) || i.skipGitErrors {
11201093
continue
11211094
}
11221095

0 commit comments

Comments
 (0)