Skip to content

Commit ec79b8b

Browse files
committed
[WIP] askrene benchmark
Signed-off-by: Lagrang3 <[email protected]>
1 parent 67432c7 commit ec79b8b

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

tests/test_askrene_bench.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from fixtures import * # noqa: F401,F403
2+
from hashlib import sha256
3+
from pyln.client import RpcError
4+
from pyln.testing.utils import SLOW_MACHINE
5+
from utils import (
6+
only_one, first_scid, GenChannel, generate_gossip_store,
7+
sync_blockheight, wait_for, TEST_NETWORK, TIMEOUT
8+
)
9+
import copy
10+
import os
11+
import pytest
12+
import subprocess
13+
import time
14+
import tempfile
15+
import random
16+
import json
17+
18+
@pytest.mark.slow_test
19+
def test_real_data(node_factory, bitcoind):
20+
outfile = tempfile.NamedTemporaryFile(prefix='gossip-store-')
21+
subprocess.check_output(['devtools/gossmap-compress',
22+
'decompress',
23+
'tests/data/gossip-store-2024-09-22.compressed',
24+
outfile.name])
25+
26+
# This is in msat, but is also the size of channel we create.
27+
AMOUNT = 100000000
28+
29+
l1 = node_factory.line_graph(1, fundamount=AMOUNT,
30+
opts=[{'gossip_store_file': outfile.name,
31+
'allow_warning': True,
32+
'dev-throttle-gossip': None}])[0]
33+
34+
# node selection
35+
all_nodes = []
36+
all_chans = l1.rpc.listchannels()["channels"]
37+
38+
node_dict = {}
39+
for c in all_chans:
40+
n = c["source"]
41+
if n not in node_dict:
42+
node_dict[n] = {"id": n, "num_chans": 0, "capacity": 0}
43+
node_dict[n]["num_chans"] += 1
44+
node_dict[n]["capacity"] += c["amount_msat"]
45+
46+
all_nodes = [ data for n, data in node_dict.items() ]
47+
48+
all_nodes.sort(key=lambda n: n["capacity"])
49+
50+
N = len(all_nodes)
51+
all_small = all_nodes[int(0.10*N): int(0.35 * N)]
52+
all_big = all_nodes[int(0.65*N): int(0.90*N)]
53+
54+
random.seed(42)
55+
amounts = [100, 1000, 10000, 100000, 1000000]
56+
num_samples = 100
57+
datapoints = []
58+
59+
def routes_fee(routes):
60+
pay = 0
61+
deliver = 0
62+
for r in routes["routes"]:
63+
deliver += r["amount_msat"]
64+
pay += r["path"][0]["amount_msat"]
65+
return pay - deliver
66+
67+
def run_sim(node_set, amt_msat, repeat, version, sample_name, data):
68+
for rep in range(repeat):
69+
print(f"BENCHMARK: running repetition {rep}, sample {sample_name} and amount {amt_msat}")
70+
# 0.5% or 5sat is the norm
71+
MAX_FEE = max(amt_msat // 200, 5000)
72+
node_sample = copy.deepcopy(node_set)
73+
src = {}
74+
dst = {}
75+
print("BENCHMARK: Selecting source node")
76+
while len(node_sample)>0:
77+
src_index = random.randint(0, len(node_sample)-1)
78+
src = copy.deepcopy(node_sample[src_index])
79+
node_sample.pop(src_index)
80+
if src["capacity"]>=amt_msat:
81+
break
82+
print("BENCHMARK: Selecting destination node")
83+
while len(node_sample)>0:
84+
dst_index = random.randint(0, len(node_sample)-1)
85+
dst = copy.deepcopy(node_sample[dst_index])
86+
node_sample.pop(dst_index)
87+
if dst["capacity"]>=amt_msat:
88+
break
89+
if dst=={} or src=={}:
90+
continue
91+
try:
92+
print("BENCHMARK: calling getroutes source=%s dest=%s" %
93+
(src["id"], dst["id"]))
94+
resp = l1.rpc.getroutes(source=src["id"],
95+
destination=dst["id"],
96+
amount_msat=amt_msat,
97+
layers=[],
98+
maxfee_msat=MAX_FEE,
99+
final_cltv=18)
100+
success = True
101+
except RpcError as e:
102+
success = False
103+
resp = e.error
104+
print(f"BENCHMARK: getroutes success {success}")
105+
line = l1.daemon.wait_for_log(
106+
"plugin-cln-askrene.*notify msg.*get_routes (completed|failed)")
107+
runtime = int(line.split()[-2])
108+
this_data = {"runtime_msec": runtime, "amount_msat": amt_msat,
109+
"version": version,
110+
"sample": sample_name, "success": success}
111+
if success:
112+
this_data["probability"] = resp["probability_ppm"] * 1e-6
113+
this_data["fee_msat"] = routes_fee(resp)
114+
else:
115+
this_data["probability"] = 0.0
116+
this_data["fee_msat"] = 0
117+
data.append(this_data)
118+
for amt_sat in amounts:
119+
run_sim(all_big, amt_sat*1000, num_samples, "default", "big", datapoints)
120+
run_sim(all_small, amt_sat*1000, num_samples, "default", "small", datapoints)
121+
with open("default_bench.json", "w") as fd:
122+
json.dump(datapoints, fd)

0 commit comments

Comments
 (0)