-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbenchmark_nodes.py
199 lines (165 loc) · 6.74 KB
/
benchmark_nodes.py
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import json
import os
import time
from typing import Any, Dict, Optional
import matplotlib.pyplot as plt
import numpy as np
from dotenv import load_dotenv
from gnosis.eth import EthereumClient
class NodeTimer:
def __init__(self, node_version: str):
self.node_version = node_version
print("Init NodeTimer for", node_version)
def get_timer(self, test_name: str) -> "Timer":
return Timer(self.node_version, test_name)
class Timer:
start: float = 0.0
elapsed: float = 0.0
benchmarks: Dict[str, Dict[str, Any]] = {}
def __init__(self, node_version: str, test_name: str):
self.node_version = node_version
self.test_name = test_name
def __enter__(self):
print(self.test_name, ":", "Starting")
self.start = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.elapsed = self.get_elapsed()
self.benchmarks.setdefault(self.node_version, {})[self.test_name] = self.elapsed
print(self.test_name, ":", self.elapsed, "seconds")
def get_elapsed(self):
return time.time() - self.start
@classmethod
def plot(cls, benchmarks: Optional[Dict[str, Any]] = None):
benchmarks = benchmarks or cls.benchmarks
node_versions = list(benchmarks.keys())
test_names = [
test_name for test_name, _ in benchmarks[node_versions[0]].items()
]
bars1 = [benchmarks[node_versions[0]][test_name] for test_name in test_names]
bars2 = [benchmarks[node_versions[1]][test_name] for test_name in test_names]
# TODO Support more bars than 2
x = np.arange(len(test_names)) # the label locations
width = 0.2
# Make the plot
fig, ax = plt.subplots()
rects1 = ax.bar(
x - width / 2,
bars1,
color="#7f6d5f",
width=width,
edgecolor="white",
label=node_versions[0],
)
rects2 = ax.bar(
x + width / 2,
bars2,
color="#557f2d",
width=width,
edgecolor="white",
label=node_versions[1],
)
ax.set_ylabel("Time elapsed in seconds (less is better)")
ax.set_title("Benchmark of Ethereum RPC")
ax.set_xticks(x, test_names)
ax.tick_params(axis="x", which="both", labelrotation=90)
ax.legend()
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
fig.subplots_adjust(bottom=0.35, top=0.96)
fig.set_size_inches(12, 7)
# plt.show()
plt.savefig("plot.png")
@classmethod
def test_plot(cls):
with open("plot.json", "r") as f:
cls.plot(benchmarks=json.load(f))
def perform_benchmark():
# Timer.test_plot()
load_dotenv()
nodes = os.getenv("ETHEREUM_NODES").split(",")
ethereum_clients = [
EthereumClient(node, provider_timeout=300, slow_provider_timeout=300)
for node in nodes
]
# Use always same block number for all the benchmarks
current_block_number = ethereum_clients[0].current_block_number
last_block_number = current_block_number - 20 # Use confirmed block
print("Last block number:", last_block_number)
for i, ethereum_client in enumerate(ethereum_clients):
node_version = ethereum_client.w3.clientVersion
node_timer = NodeTimer(node_version)
last_block = ethereum_client.get_block(
last_block_number, full_transactions=False
)
with node_timer.get_timer("Txs in last block") as timer:
ethereum_client.get_transactions(last_block["transactions"])
with node_timer.get_timer("Tx traces in last block") as timer:
ethereum_client.parity.trace_transactions(last_block["transactions"])
# Get block from last year
old_block = ethereum_client.get_block(
last_block["number"] - 2102400, full_transactions=False
)
with node_timer.get_timer("Txs in last year block") as timer:
ethereum_client.get_transactions(old_block["transactions"])
with node_timer.get_timer("Tx traces in last year block") as timer:
ethereum_client.parity.trace_transactions(old_block["transactions"])
with node_timer.get_timer(
"Erc20 transfers in last 500 blocks" # We don't know the number of events beforehand
) as timer:
number_events = len(
ethereum_client.erc20.get_total_transfer_history(
from_block=last_block_number - 500, to_block=last_block_number
)
)
print(number_events)
timer.test_name = (
f"Erc20 transfers in last \n500 blocks - {number_events} events"
)
with node_timer.get_timer(
"Traces for Gnosis Safe v1.1.1 last 200 blocks" # We don't know the number of events before hand
) as timer:
# 0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F was deployed on 9084503
number_traces = len(
ethereum_client.parity.trace_filter(
from_block=last_block_number - 200,
to_block=last_block_number,
to_address=["0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F"],
)
)
print(number_traces)
timer.test_name = f"Traces for Gnosis Safe v1.1.1 \nlast 200 blocks (30 minutes)\n{number_traces} traces"
with node_timer.get_timer(
"Traces for Gnosis Safe v1.1.1 \nfirst 100,000 blocks (17 days)\n5 traces"
) as timer:
# 0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F was deployed on 9084503
from_block = 9084503
print(
len(
ethereum_client.parity.trace_filter(
from_block=from_block,
to_block=from_block + 100_000,
to_address=["0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F"],
)
)
)
with node_timer.get_timer(
"Traces for Gnosis Safe v1.1.1 \nfirst 250,000 blocks (1.5 months)\n278 traces"
) as timer:
# 0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F was deployed on 9084503
from_block = 9084503
print(
len(
ethereum_client.parity.trace_filter(
from_block=from_block,
to_block=from_block + 250_000,
to_address=["0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F"],
)
)
)
print()
Timer.plot()
with open("plot.json", "w") as f:
json.dump(Timer.benchmarks, f, indent=4)
if __name__ == "__main__":
perform_benchmark()