Skip to content

Commit

Permalink
Don't use bytes.Buffer unless necessary.
Browse files Browse the repository at this point in the history
In most of the cases we know exactly how many bytes we actually need
to copy around, so just copy directly into a properly sized byte slice.

`bytes.Buffer` pre-allocates 64 bytes at minimum, which is more than
we actually use in the majority of cases here since UUIDs are 16 bytes.
  • Loading branch information
sidnei committed Mar 23, 2022
1 parent 852c60c commit a4858e5
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 19 deletions.
10 changes: 6 additions & 4 deletions storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ type LookupOptions struct {

// String returns a readable version of the LookupOptions instance.
func (l *LookupOptions) String() string {
b := bytes.NewBufferString("<limit=")
var b bytes.Buffer
b.Grow(80) // We already know we will be writing at least this much from the fixed strings below.
b.WriteString("<limit=")
b.WriteString(strconv.Itoa(l.MaxElements))
b.WriteString(", lower_anchor=")
if l.LowerAnchor != nil {
Expand All @@ -75,9 +77,9 @@ func (l *LookupOptions) String() string {

// UUID return the UUID of the lookup option.
func (l *LookupOptions) UUID() uuid.UUID {
var buffer bytes.Buffer
buffer.WriteString(l.String())
return uuid.NewSHA1(uuid.NIL, buffer.Bytes())
b := make([]byte, len(l.String()))
copy(b, l.String())
return uuid.NewSHA1(uuid.NIL, b)
}

// DefaultLookup provides the default lookup behavior.
Expand Down
2 changes: 1 addition & 1 deletion triple/literal/literal.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func (l *Literal) UUID() uuid.UUID {
binary.LittleEndian.PutUint64(b, bs)
buffer.Write(b)
case string:
buffer.Write([]byte(v))
buffer.WriteString(v)
case []byte:
buffer.Write(v)
}
Expand Down
8 changes: 4 additions & 4 deletions triple/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ func NewBlankNode() *Node {
// UUID returns a global unique identifier for the given node. It is
// implemented as the SHA1 UUID of the node values.
func (n *Node) UUID() uuid.UUID {
var buffer bytes.Buffer
buffer.WriteString(string(*n.t))
buffer.WriteString(string(*n.id))
return uuid.NewSHA1(uuid.NIL, buffer.Bytes())
b := make([]byte, len(*n.t)+len(*n.id))
copy(b[:len(*n.t)], *n.t)
copy(b[len(*n.t):], *n.id)
return uuid.NewSHA1(uuid.NIL, b)
}
14 changes: 14 additions & 0 deletions triple/node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package node

import (
"bytes"
"testing"

"github.com/pborman/uuid"
Expand Down Expand Up @@ -185,3 +186,16 @@ func TestBlankNode(t *testing.T) {
}
}
}

func TestUUID(t *testing.T) {
n, err := Parse("/foo<123>")
if err != nil {
t.Errorf("node.Parse: failed to parse '/foo<123>'; %v", err)
}
var buffer bytes.Buffer
buffer.WriteString(string(*n.t))
buffer.WriteString(string(*n.id))
if !uuid.Equal(n.UUID(), uuid.NewSHA1(uuid.NIL, buffer.Bytes())) {
t.Fatalf("node.UUID not equal; got %q, want: %q", n.UUID(), uuid.NewSHA1(uuid.NIL, buffer.Bytes()))
}
}
6 changes: 3 additions & 3 deletions triple/predicate/predicate.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (p *Predicate) UUID() uuid.UUID {
// is only useful for driver implementers when they want to take advantage
// of range reads.
func (p *Predicate) PartialUUID() uuid.UUID {
var buffer bytes.Buffer
buffer.WriteString(string(p.id))
return uuid.NewSHA1(uuid.NIL, buffer.Bytes())
b := make([]byte, len(p.id))
copy(b, p.id)
return uuid.NewSHA1(uuid.NIL, b)
}
13 changes: 6 additions & 7 deletions triple/triple.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package triple

import (
"bytes"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -255,11 +254,11 @@ func (t *Triple) Reify() ([]*Triple, *node.Node, error) {
// implemented as the SHA1 UUID of the concatenated UUIDs of the subject,
// predicate, and object.
func (t *Triple) UUID() uuid.UUID {
var buffer bytes.Buffer
ul := len(t.s.UUID())
b := make([]byte, 3*ul)

buffer.Write([]byte(t.s.UUID()))
buffer.Write([]byte(t.p.UUID()))
buffer.Write([]byte(t.o.UUID()))

return uuid.NewSHA1(uuid.NIL, buffer.Bytes())
copy(b[:ul], t.s.UUID())
copy(b[ul:2*ul], t.p.UUID())
copy(b[2*ul:], t.o.UUID())
return uuid.NewSHA1(uuid.NIL, b)
}
9 changes: 9 additions & 0 deletions triple/triple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
package triple

import (
"bytes"
"testing"

"github.com/google/badwolf/triple/literal"
"github.com/google/badwolf/triple/node"
"github.com/google/badwolf/triple/predicate"
"github.com/pborman/uuid"
)

func getTestData(t *testing.T) (*node.Node, *predicate.Predicate, *Object) {
Expand Down Expand Up @@ -179,5 +181,12 @@ func TestUUID(t *testing.T) {
if !t1.Equal(t2) {
t.Errorf("Failed to equal %s(%s) == %s(%s)", t1, t1.UUID(), t2, t2.UUID())
}
var b bytes.Buffer
b.Write(t1.s.UUID())
b.Write(t1.p.UUID())
b.Write(t1.o.UUID())
if !uuid.Equal(t1.UUID(), uuid.NewSHA1(uuid.NIL, b.Bytes())) {
t.Errorf("Failed to equal %s == %s", t1.UUID(), uuid.NewSHA1(uuid.NIL, b.Bytes()))
}
}
}

0 comments on commit a4858e5

Please sign in to comment.