-
Notifications
You must be signed in to change notification settings - Fork 75
/
MerklePatriciaTreeSpeedSpec.scala
74 lines (62 loc) · 2.6 KB
/
MerklePatriciaTreeSpeedSpec.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package io.iohk.ethereum.mpt
import io.iohk.ethereum.db.dataSource.EphemDataSource
import io.iohk.ethereum.db.storage.{ArchiveNodeStorage, MptStorage, NodeStorage, SerializingMptStorage}
import io.iohk.ethereum.mpt.MerklePatriciaTrie.defaultByteArraySerializable
import io.iohk.ethereum.utils.Logger
import io.iohk.ethereum.{ObjectGenerators, crypto}
import org.bouncycastle.util.encoders.Hex
import org.scalatest.FunSuite
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class MerklePatriciaTreeSpeedSpec
extends FunSuite
with ScalaCheckPropertyChecks
with ObjectGenerators
with Logger
with PersistentStorage {
test("Performance test (From: https://github.com/ethereum/wiki/wiki/Benchmarks)") {
val Rounds = 1000
val Symmetric = true
val start: Long = System.currentTimeMillis
val emptyTrie = MerklePatriciaTrie[Array[Byte], Array[Byte]](
new SerializingMptStorage(new ArchiveNodeStorage(new NodeStorage(EphemDataSource())))
)
var seed: Array[Byte] = Array.fill(32)(0.toByte)
val trieResult = (0 until Rounds).foldLeft(emptyTrie) { case (recTrie, i) =>
seed = Node.hashFn(seed)
if (!Symmetric) recTrie.put(seed, seed)
else {
val mykey = seed
seed = Node.hashFn(seed)
val myval = if ((seed(0) & 0xff) % 2 == 1) Array[Byte](seed.last) else seed
recTrie.put(mykey, myval)
}
}
val rootHash = Hex.toHexString(trieResult.getRootHash)
log.info("Time taken(ms): " + (System.currentTimeMillis - start))
log.info("Root hash obtained: " + rootHash)
if (Symmetric) assert(rootHash.take(4) == "36f6" && rootHash.drop(rootHash.length - 4) == "93a3")
else assert(rootHash.take(4) == "da8a" && rootHash.drop(rootHash.length - 4) == "0ca4")
}
test("MPT benchmark with RocksDb") {
withRocksDbNodeStorage { ns =>
mptBenchmarkTest(ns)
}
}
def mptBenchmarkTest(ns: MptStorage): MerklePatriciaTrie[Array[Byte], Array[Byte]] = {
val hashFn = crypto.kec256(_: Array[Byte])
val defaultByteArraySer = MerklePatriciaTrie.defaultByteArraySerializable
val EmptyTrie = MerklePatriciaTrie[Array[Byte], Array[Byte]](ns)(defaultByteArraySer, defaultByteArraySer)
var t = System.currentTimeMillis()
(1 to 20000000).foldLeft(EmptyTrie) { case (trie, i) =>
val k = hashFn(("hello" + i).getBytes)
val v = hashFn(("world" + i).getBytes)
if (i % 100000 == 0) {
val newT = System.currentTimeMillis()
val delta = (newT - t) / 1000.0
t = newT
log.debug(s"=== $i elements put, time for batch is: $delta sec")
}
trie.put(k, v)
}
}
}