@@ -26,6 +26,7 @@ import (
2626 "math/rand"
2727 "reflect"
2828 "sort"
29+ "strings"
2930 "testing"
3031 "testing/quick"
3132
@@ -35,6 +36,7 @@ import (
3536 "github.com/ethereum/go-ethereum/core/types"
3637 "github.com/ethereum/go-ethereum/crypto"
3738 "github.com/ethereum/go-ethereum/ethdb"
39+ "github.com/ethereum/go-ethereum/internal/testrand"
3840 "github.com/ethereum/go-ethereum/rlp"
3941 "github.com/ethereum/go-ethereum/trie/trienode"
4042 "github.com/holiman/uint256"
@@ -1206,3 +1208,105 @@ func FuzzTrie(f *testing.F) {
12061208 }
12071209 })
12081210}
1211+
1212+ func BenchmarkCommit (b * testing.B ) {
1213+ benchmarkCommit (b , 100 )
1214+ benchmarkCommit (b , 500 )
1215+ benchmarkCommit (b , 2000 )
1216+ benchmarkCommit (b , 5000 )
1217+ }
1218+
1219+ func benchmarkCommit (b * testing.B , n int ) {
1220+ b .Run (fmt .Sprintf ("commit-%vnodes-sequential" , n ), func (b * testing.B ) {
1221+ testCommit (b , n , false )
1222+ })
1223+ b .Run (fmt .Sprintf ("commit-%vnodes-parallel" , n ), func (b * testing.B ) {
1224+ testCommit (b , n , true )
1225+ })
1226+ }
1227+
1228+ func testCommit (b * testing.B , n int , parallel bool ) {
1229+ tries := make ([]* Trie , b .N )
1230+ for i := 0 ; i < b .N ; i ++ {
1231+ tries [i ] = NewEmpty (nil )
1232+ for j := 0 ; j < n ; j ++ {
1233+ key := testrand .Bytes (32 )
1234+ val := testrand .Bytes (32 )
1235+ tries [i ].Update (key , val )
1236+ }
1237+ tries [i ].Hash ()
1238+ if ! parallel {
1239+ tries [i ].uncommitted = 0
1240+ }
1241+ }
1242+ b .ResetTimer ()
1243+ b .ReportAllocs ()
1244+ for i := 0 ; i < len (tries ); i ++ {
1245+ tries [i ].Commit (true )
1246+ }
1247+ }
1248+
1249+ func TestCommitCorrect (t * testing.T ) {
1250+ var paraTrie = NewEmpty (nil )
1251+ var refTrie = NewEmpty (nil )
1252+
1253+ for j := 0 ; j < 5000 ; j ++ {
1254+ key := testrand .Bytes (32 )
1255+ val := testrand .Bytes (32 )
1256+ paraTrie .Update (key , val )
1257+ refTrie .Update (common .CopyBytes (key ), common .CopyBytes (val ))
1258+ }
1259+ paraTrie .Hash ()
1260+ refTrie .Hash ()
1261+ refTrie .uncommitted = 0
1262+
1263+ haveRoot , haveNodes := paraTrie .Commit (true )
1264+ wantRoot , wantNodes := refTrie .Commit (true )
1265+
1266+ if haveRoot != wantRoot {
1267+ t .Fatalf ("have %x want %x" , haveRoot , wantRoot )
1268+ }
1269+ have := printSet (haveNodes )
1270+ want := printSet (wantNodes )
1271+ if have != want {
1272+ i := 0
1273+ for i = 0 ; i < len (have ); i ++ {
1274+ if have [i ] != want [i ] {
1275+ break
1276+ }
1277+ }
1278+ if i > 100 {
1279+ i -= 100
1280+ }
1281+ t .Fatalf ("have != want\n have %q\n want %q" , have [i :], want [i :])
1282+ }
1283+ }
1284+ func printSet (set * trienode.NodeSet ) string {
1285+ var out = new (strings.Builder )
1286+ fmt .Fprintf (out , "nodeset owner: %v\n " , set .Owner )
1287+ var paths []string
1288+ for k := range set .Nodes {
1289+ paths = append (paths , k )
1290+ }
1291+ sort .Strings (paths )
1292+
1293+ for _ , path := range paths {
1294+ n := set .Nodes [path ]
1295+ // Deletion
1296+ if n .IsDeleted () {
1297+ fmt .Fprintf (out , " [-]: %x\n " , path )
1298+ continue
1299+ }
1300+ // Insertion or update
1301+ fmt .Fprintf (out , " [+/*]: %x -> %v \n " , path , n .Hash )
1302+ }
1303+ sort .Slice (set .Leaves , func (i , j int ) bool {
1304+ a := set .Leaves [i ]
1305+ b := set .Leaves [j ]
1306+ return bytes .Compare (a .Parent [:], b .Parent [:]) < 0
1307+ })
1308+ for _ , n := range set .Leaves {
1309+ fmt .Fprintf (out , "[leaf]: %v\n " , n )
1310+ }
1311+ return out .String ()
1312+ }
0 commit comments