2024-06-06 12:33:49 +00:00
|
|
|
import pandas as pd
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import os
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
plt.rcParams["figure.figsize"] = [40, 30]
|
|
|
|
|
|
|
|
from pandas.plotting import register_matplotlib_converters
|
|
|
|
|
|
|
|
register_matplotlib_converters()
|
|
|
|
|
|
|
|
|
|
|
|
def readStats(name: str, min_block_number: int):
|
|
|
|
df = pd.read_csv(name).convert_dtypes()
|
eth: bump (#2308)
* eth: bump
Speed up basic operations like hashing and creating RLP:s - up to 25%
improvement in certain block ranges!
```
876729c.csv /data/nimbus_stats/stats-20240605_2204-ed4f6221.csv
stats-20240605_2000-c876729c.csv vs stats-20240605_2204-ed4f6221.csv
bps_x bps_y tps_x tps_y bpsd tpsd timed
block_number
(500001, 888889] 1,017.72 996.07 1,784.96 1742.438676 -2.72% -2.72% 3.31%
(888889, 1277778] 528.00 536.30 2,159.79 2198.781046 1.69% 1.69% -1.44%
(1277778, 1666667] 324.29 317.78 2,064.48 2008.106377 -2.82% -2.82% 3.33%
(1666667, 2055556] 253.87 258.74 1,840.94 1872.935273 1.67% 1.67% -1.39%
(2055556, 2444445] 175.79 178.66 1,340.61 1363.248939 0.93% 0.93% -0.74%
(2444445, 2833334] 137.27 159.74 958.75 1113.323757 14.24% 14.24% -10.69%
(2833334, 3222223] 170.48 228.63 1,272.70 1704.047195 34.41% 34.41% -25.17%
(3222223, 3611112] 127.49 125.48 1,572.39 1548.835791 -1.19% -1.19% 1.47%
(3611112, 4000001] 37.25 40.42 1,100.65 1184.740493 9.58% 9.58% -7.04%
blocks: 3501696, baseline: 11h59m40s, contender: 11h21m38s
bpsd (mean): 6.18%
tpsd (mean): 6.18%
Time (sum): -38m1s, -4.26%
bpsd = blocks per sec diff (+), tpsd = txs per sec diff, timed = time to process diff (-)
+ = more is better, - = less is better
```
* ignore gitignore
2024-06-06 23:39:09 +00:00
|
|
|
if len(df.index) > 2 * min_block_number:
|
|
|
|
df = df[df.block_number >= min_block_number]
|
2024-06-06 12:33:49 +00:00
|
|
|
df.set_index("block_number", inplace=True)
|
|
|
|
df.time /= 1000000000
|
|
|
|
df.drop(columns=["gas"], inplace=True)
|
|
|
|
df["bps"] = df.blocks / df.time
|
|
|
|
df["tps"] = df.txs / df.time
|
|
|
|
return df
|
|
|
|
|
|
|
|
|
|
|
|
def prettySecs(s: float):
|
|
|
|
sa = abs(int(s))
|
|
|
|
ss = sa % 60
|
|
|
|
m = sa // 60 % 60
|
|
|
|
h = sa // (60 * 60)
|
|
|
|
sign = "" if s >= 0 else "-"
|
|
|
|
|
|
|
|
if h > 0:
|
|
|
|
return f"{sign}{h}h{m}m{ss}s"
|
|
|
|
elif m > 0:
|
|
|
|
return f"{sign}{m}m{ss}s"
|
|
|
|
else:
|
|
|
|
return f"{sign}{ss}s"
|
|
|
|
|
|
|
|
|
|
|
|
def formatBins(df: pd.DataFrame, bins: int):
|
|
|
|
if bins > 0:
|
|
|
|
bins = np.linspace(
|
|
|
|
df.block_number.iloc[0], df.block_number.iloc[-1], bins, dtype=int
|
|
|
|
)
|
|
|
|
return df.groupby(pd.cut(df["block_number"], bins), observed=True)
|
|
|
|
else:
|
|
|
|
return df
|
|
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("baseline")
|
|
|
|
parser.add_argument("contender")
|
|
|
|
parser.add_argument("--plot", action="store_true")
|
|
|
|
parser.add_argument(
|
|
|
|
"--bins",
|
|
|
|
default=10,
|
|
|
|
type=int,
|
|
|
|
help="Number of bins to group block ranges into in overview, 0=all rows",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--min-block-number",
|
|
|
|
default=500000,
|
|
|
|
type=int,
|
|
|
|
help="Skip block blocks below the given number",
|
|
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
baseline = readStats(args.baseline, args.min_block_number)
|
|
|
|
contender = readStats(args.contender, args.min_block_number)
|
|
|
|
|
|
|
|
# Pick out the rows to match - a more sophisticated version of this would
|
|
|
|
# interpolate, perhaps - also, maybe should check for non-matching block/tx counts
|
|
|
|
df = baseline.merge(contender, on=("block_number", "blocks", "txs"))
|
|
|
|
|
|
|
|
df["bpsd"] = (df.bps_y - df.bps_x) / df.bps_x
|
|
|
|
df["tpsd"] = (df.tps_y - df.tps_x) / df.tps_x
|
|
|
|
df["timed"] = (df.time_y - df.time_x) / df.time_x
|
|
|
|
|
|
|
|
df.reset_index(inplace=True)
|
|
|
|
|
|
|
|
if args.plot:
|
|
|
|
plt.rcParams["axes.grid"] = True
|
|
|
|
|
|
|
|
fig = plt.figure()
|
|
|
|
bps = fig.add_subplot(2, 2, 1, title="Blocks per second (more is better)")
|
|
|
|
bpsd = fig.add_subplot(2, 2, 2, title="Difference (>0 is better)")
|
|
|
|
tps = fig.add_subplot(2, 2, 3, title="Transactions per second (more is better)")
|
|
|
|
tpsd = fig.add_subplot(2, 2, 4, title="Difference (>0 is better)")
|
|
|
|
|
|
|
|
bps.plot(df.block_number, df.bps_x.rolling(3).mean(), label="baseline")
|
|
|
|
bps.plot(df.block_number, df.bps_y.rolling(3).mean(), label="contender")
|
|
|
|
|
|
|
|
bpsd.plot(df.block_number, df.bpsd.rolling(3).mean())
|
|
|
|
|
|
|
|
tps.plot(df.block_number, df.tps_x.rolling(3).mean(), label="baseline")
|
|
|
|
tps.plot(df.block_number, df.tps_y.rolling(3).mean(), label="contender")
|
|
|
|
|
|
|
|
tpsd.plot(df.block_number, df.tpsd.rolling(3).mean())
|
|
|
|
|
|
|
|
bps.legend()
|
|
|
|
tps.legend()
|
|
|
|
|
|
|
|
fig.subplots_adjust(bottom=0.05, right=0.95, top=0.95, left=0.05)
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
print(f"{os.path.basename(args.baseline)} vs {os.path.basename(args.contender)}")
|
|
|
|
print(
|
|
|
|
formatBins(df, args.bins)
|
|
|
|
.agg(
|
|
|
|
dict.fromkeys(
|
|
|
|
["bps_x", "bps_y", "tps_x", "tps_y", "bpsd", "tpsd", "timed"], "mean"
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.to_string(
|
|
|
|
formatters=dict(
|
|
|
|
dict.fromkeys(["bpsd", "tpsd", "timed"], "{:,.2%}".format),
|
|
|
|
**dict.fromkeys(["bps_x", "bps_y", "tps_x"], "{:,.2f}".format),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
print(
|
|
|
|
f"\nblocks: {df.blocks.sum()}, baseline: {prettySecs(df.time_x.sum())}, contender: {prettySecs(df.time_y.sum())}"
|
|
|
|
)
|
|
|
|
print(f"bpsd (mean): {df.bpsd.mean():.2%}")
|
|
|
|
print(f"tpsd (mean): {df.tpsd.mean():.2%}")
|
|
|
|
print(
|
|
|
|
f"Time (sum): {prettySecs(df.time_y.sum()-df.time_x.sum())}, {df.timed.mean():.2%}"
|
|
|
|
)
|
|
|
|
|
|
|
|
print()
|
|
|
|
print(
|
|
|
|
"bpsd = blocks per sec diff (+), tpsd = txs per sec diff, timed = time to process diff (-)"
|
|
|
|
)
|
|
|
|
print("+ = more is better, - = less is better")
|