Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Commit

Permalink
Improve treeHasher performance (#42)
Browse files Browse the repository at this point in the history
By doing two things:

 - Pre-allocated enough size for slice, instead of initializing a small
   one then continuously appending to it.
 - Initializing placeholder slice once instead of creating new one
   everytime treeHasher.placeholder is called.

That helps improves the sppeed, and less allocations for Update/Delete
operations:

name                       old time/op    new time/op    delta
SparseMerkleTree_Update-8    11.9µs ± 3%    11.2µs ± 3%   -5.89%  (p=0.008 n=5+5)
SparseMerkleTree_Delete-8    9.66µs ± 2%    5.40µs ± 2%  -44.12%  (p=0.008 n=5+5)

name                       old alloc/op   new alloc/op   delta
SparseMerkleTree_Update-8    17.7kB ± 0%    16.1kB ± 1%   -9.42%  (p=0.016 n=4+5)
SparseMerkleTree_Delete-8    16.3kB ± 0%    13.9kB ± 0%  -14.82%  (p=0.008 n=5+5)

name                       old allocs/op  new allocs/op  delta
SparseMerkleTree_Update-8       117 ± 0%        63 ± 0%  -46.15%  (p=0.029 n=4+4)
SparseMerkleTree_Delete-8      94.4 ± 1%      28.6 ± 2%  -69.70%  (p=0.008 n=5+5)
  • Loading branch information
cuonglm authored Jul 14, 2021
1 parent 072abf0 commit a431f73
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
36 changes: 36 additions & 0 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package smt

import (
"crypto/sha256"
"strconv"
"testing"
)

func BenchmarkSparseMerkleTree_Update(b *testing.B) {
smn, smv := NewSimpleMap(), NewSimpleMap()
smt := NewSparseMerkleTree(smn, smv, sha256.New())

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := strconv.Itoa(i)
_, _ = smt.Update([]byte(s), []byte(s))
}
}

func BenchmarkSparseMerkleTree_Delete(b *testing.B) {
smn, smv := NewSimpleMap(), NewSimpleMap()
smt := NewSparseMerkleTree(smn, smv, sha256.New())

for i := 0; i < 100000; i++ {
s := strconv.Itoa(i)
_, _ = smt.Update([]byte(s), []byte(s))
}

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := strconv.Itoa(i)
_, _ = smt.Delete([]byte(s))
}
}
20 changes: 9 additions & 11 deletions treehasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ var leafPrefix = []byte{0}
var nodePrefix = []byte{1}

type treeHasher struct {
hasher hash.Hash
hasher hash.Hash
zeroValue []byte
}

func newTreeHasher(hasher hash.Hash) *treeHasher {
th := treeHasher{
hasher: hasher,
}
th := treeHasher{hasher: hasher}
th.zeroValue = make([]byte, th.pathSize())

return &th
}
Expand All @@ -32,9 +32,8 @@ func (th *treeHasher) path(key []byte) []byte {
}

func (th *treeHasher) digestLeaf(path []byte, leafData []byte) ([]byte, []byte) {
value := make([]byte, len(leafPrefix))
copy(value, leafPrefix)

value := make([]byte, 0, len(leafPrefix)+len(path)+len(leafData))
value = append(value, leafPrefix...)
value = append(value, path...)
value = append(value, leafData...)

Expand All @@ -54,9 +53,8 @@ func (th *treeHasher) isLeaf(data []byte) bool {
}

func (th *treeHasher) digestNode(leftData []byte, rightData []byte) ([]byte, []byte) {
value := make([]byte, len(nodePrefix))
copy(value, nodePrefix)

value := make([]byte, 0, len(nodePrefix)+len(leftData)+len(rightData))
value = append(value, nodePrefix...)
value = append(value, leftData...)
value = append(value, rightData...)

Expand All @@ -76,5 +74,5 @@ func (th *treeHasher) pathSize() int {
}

func (th *treeHasher) placeholder() []byte {
return bytes.Repeat([]byte{0}, th.pathSize())
return th.zeroValue
}

0 comments on commit a431f73

Please sign in to comment.