Skip to content

Commit

Permalink
Optimise Reference.String()
Browse files Browse the repository at this point in the history
Decreases allocations and bytes per operation by using string builder
with a predefined size.

One additional allocation has been removed by using its own implementation
of Strings(). The reason behind this was due to the fact the calls to
.String() are more recurrent than .Strings() and the performance impact
was worth the code duplication.

Benchmark results:
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
name                        old time/op    new time/op    delta
ReferenceStringSymbolic-16     140ns ± 4%      40ns ± 9%  -71.19%  (p=0.008 n=5+5)
ReferenceStringHash-16         174ns ±14%      85ns ± 4%  -51.13%  (p=0.008 n=5+5)
ReferenceStringInvalid-16     48.9ns ± 2%     1.5ns ± 3%  -96.96%  (p=0.008 n=5+5)

name                        old alloc/op   new alloc/op   delta
ReferenceStringSymbolic-16     88.0B ± 0%     32.0B ± 0%  -63.64%  (p=0.008 n=5+5)
ReferenceStringHash-16          176B ± 0%      144B ± 0%  -18.18%  (p=0.008 n=5+5)
ReferenceStringInvalid-16      0.00B          0.00B          ~     (all equal)

name                        old allocs/op  new allocs/op  delta
ReferenceStringSymbolic-16      4.00 ± 0%      1.00 ± 0%  -75.00%  (p=0.008 n=5+5)
ReferenceStringHash-16          5.00 ± 0%      3.00 ± 0%  -40.00%  (p=0.008 n=5+5)
ReferenceStringInvalid-16       0.00           0.00          ~     (all equal)

Signed-off-by: Paulo Gomes <pjbgf@linux.com>
  • Loading branch information
pjbgf committed Nov 7, 2022
1 parent 123cdde commit ffa7e69
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
19 changes: 17 additions & 2 deletions plumbing/reference.go
Expand Up @@ -204,6 +204,21 @@ func (r *Reference) Strings() [2]string {
}

func (r *Reference) String() string {
s := r.Strings()
return fmt.Sprintf("%s %s", s[1], s[0])
ref := ""
switch r.Type() {
case HashReference:
ref = r.Hash().String()
case SymbolicReference:
ref = symrefPrefix + r.Target().String()
default:
return ""
}

name := r.Name().String()
var v strings.Builder
v.Grow(len(ref) + len(name) + 1)
v.WriteString(ref)
v.WriteString(" ")
v.WriteString(name)
return v.String()
}
24 changes: 23 additions & 1 deletion plumbing/reference_test.go
@@ -1,6 +1,10 @@
package plumbing

import . "gopkg.in/check.v1"
import (
"testing"

. "gopkg.in/check.v1"
)

type ReferenceSuite struct{}

Expand Down Expand Up @@ -98,3 +102,21 @@ func (s *ReferenceSuite) TestIsTag(c *C) {
r := ReferenceName("refs/tags/v3.1.")
c.Assert(r.IsTag(), Equals, true)
}

func benchMarkReferenceString(r *Reference, b *testing.B) {
for n := 0; n < b.N; n++ {
r.String()
}
}

func BenchmarkReferenceStringSymbolic(b *testing.B) {
benchMarkReferenceString(NewSymbolicReference("v3.1.1", "refs/tags/v3.1.1"), b)
}

func BenchmarkReferenceStringHash(b *testing.B) {
benchMarkReferenceString(NewHashReference("v3.1.1", NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")), b)
}

func BenchmarkReferenceStringInvalid(b *testing.B) {
benchMarkReferenceString(&Reference{}, b)
}

0 comments on commit ffa7e69

Please sign in to comment.