Skip to content

Commit b4939fa

Browse files
Benchmark OM pathfinding
1 parent 7f6b8cc commit b4939fa

File tree

2 files changed

+114
-35
lines changed

2 files changed

+114
-35
lines changed

lightning/src/routing/onion_message.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub fn find_path<L: Deref, GL: Deref>(
5858
if let Some(first_hops) = first_hops {
5959
for hop in first_hops {
6060
if hop.counterparty.node_id == *our_node_pubkey { return Err(Error::InvalidFirstHop) }
61+
#[cfg(not(feature = "_bench_unstable"))]
6162
if !hop.counterparty.features.supports_onion_messages() { continue; }
6263
let node_id = NodeId::from_pubkey(&hop.counterparty.node_id);
6364
frontier.push(PathBuildingHop { cost: 1, node_id, parent_node_id: start });
@@ -80,6 +81,7 @@ pub fn find_path<L: Deref, GL: Deref>(
8081
// Only consider the network graph if first_hops does not override it.
8182
if valid_first_hops.contains(&node_id) || node_id == our_node_id {
8283
} else if let Some(node_ann) = &node_info.announcement_info {
84+
#[cfg(not(feature = "_bench_unstable"))]
8385
if !node_ann.features.supports_onion_messages() || node_ann.features.requires_unknown_bits()
8486
{ continue; }
8587
} else { continue; }
@@ -276,3 +278,72 @@ mod tests {
276278
assert_eq!(path.len(), 2);
277279
}
278280
}
281+
282+
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
283+
mod benches {
284+
use super::*;
285+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
286+
use crate::routing::gossip::NetworkGraph;
287+
use crate::routing::router::bench_utils;
288+
use crate::test::Bencher;
289+
use crate::util::logger::{Logger, Record};
290+
use crate::util::ser::ReadableArgs;
291+
292+
struct DummyLogger {}
293+
impl Logger for DummyLogger {
294+
fn log(&self, _record: &Record) {}
295+
}
296+
297+
fn read_network_graph(logger: &DummyLogger) -> NetworkGraph<&DummyLogger> {
298+
let mut d = bench_utils::get_route_file().unwrap();
299+
NetworkGraph::read(&mut d, logger).unwrap()
300+
}
301+
302+
#[bench]
303+
fn generate_simple_routes(bench: &mut Bencher) {
304+
let logger = DummyLogger {};
305+
let network_graph = read_network_graph(&logger);
306+
generate_routes(bench, &network_graph);
307+
}
308+
309+
fn payer_pubkey() -> PublicKey {
310+
let secp_ctx = Secp256k1::new();
311+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
312+
}
313+
314+
fn generate_routes(
315+
bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>,
316+
) {
317+
let nodes = graph.read_only().nodes().clone();
318+
let payer = payer_pubkey();
319+
320+
// Get 100 (source, destination) pairs for which route-getting actually succeeds...
321+
let mut routes = Vec::new();
322+
let mut route_endpoints = Vec::new();
323+
let mut seed: usize = 0xdeadbeef;
324+
'load_endpoints: for _ in 0..150 {
325+
loop {
326+
seed *= 0xdeadbeef;
327+
let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
328+
let first_hop = bench_utils::first_hop(src);
329+
seed *= 0xdeadbeef;
330+
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
331+
if let Ok(route) = find_path(&payer, &dst, &graph, Some(&[&first_hop]), &DummyLogger{}) {
332+
routes.push(route);
333+
route_endpoints.push((first_hop, dst));
334+
continue 'load_endpoints;
335+
}
336+
}
337+
}
338+
route_endpoints.truncate(100);
339+
assert_eq!(route_endpoints.len(), 100);
340+
341+
// Benchmark finding paths between the nodes we learned.
342+
let mut idx = 0;
343+
bench.iter(|| {
344+
let (first_hop, dst) = &route_endpoints[idx % route_endpoints.len()];
345+
assert!(find_path(&payer, &dst, &graph, Some(&[first_hop]), &DummyLogger{}).is_ok());
346+
idx += 1;
347+
});
348+
}
349+
}

lightning/src/routing/router.rs

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5609,7 +5609,11 @@ mod tests {
56095609

56105610
#[cfg(all(test, not(feature = "no-std")))]
56115611
pub(crate) mod bench_utils {
5612+
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
5613+
use bitcoin::secp256k1::PublicKey;
5614+
56125615
use std::fs::File;
5616+
56135617
/// Tries to open a network graph file, or panics with a URL to fetch it.
56145618
pub(crate) fn get_route_file() -> Result<std::fs::File, &'static str> {
56155619
let res = File::open("net_graph-2023-01-18.bin") // By default we're run in RL/lightning
@@ -5632,42 +5636,15 @@ pub(crate) mod bench_utils {
56325636
#[cfg(not(require_route_graph_test))]
56335637
return res;
56345638
}
5635-
}
5636-
5637-
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
5638-
mod benches {
5639-
use super::*;
5640-
use bitcoin::hashes::Hash;
5641-
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
5642-
use crate::chain::transaction::OutPoint;
5643-
use crate::chain::keysinterface::{EntropySource, KeysManager};
5644-
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
5645-
use crate::ln::features::InvoiceFeatures;
5646-
use crate::routing::gossip::NetworkGraph;
5647-
use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters};
5648-
use crate::util::config::UserConfig;
5649-
use crate::util::logger::{Logger, Record};
5650-
use crate::util::ser::ReadableArgs;
5651-
5652-
use test::Bencher;
5653-
5654-
struct DummyLogger {}
5655-
impl Logger for DummyLogger {
5656-
fn log(&self, _record: &Record) {}
5657-
}
5658-
5659-
fn read_network_graph(logger: &DummyLogger) -> NetworkGraph<&DummyLogger> {
5660-
let mut d = bench_utils::get_route_file().unwrap();
5661-
NetworkGraph::read(&mut d, logger).unwrap()
5662-
}
5663-
5664-
fn payer_pubkey() -> PublicKey {
5665-
let secp_ctx = Secp256k1::new();
5666-
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
5667-
}
56685639

56695640
#[inline]
5670-
fn first_hop(node_id: PublicKey) -> ChannelDetails {
5641+
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
5642+
pub(crate) fn first_hop(node_id: PublicKey) -> crate::ln::channelmanager::ChannelDetails {
5643+
use bitcoin::hashes::Hash;
5644+
use crate::chain::transaction::OutPoint;
5645+
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
5646+
use crate::util::config::UserConfig;
5647+
56715648
ChannelDetails {
56725649
channel_id: [0; 32],
56735650
counterparty: ChannelCounterparty {
@@ -5704,6 +5681,37 @@ mod benches {
57045681
config: None,
57055682
}
57065683
}
5684+
}
5685+
5686+
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
5687+
mod benches {
5688+
use super::*;
5689+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
5690+
use crate::chain::keysinterface::{EntropySource, KeysManager};
5691+
use crate::ln::channelmanager;
5692+
use crate::ln::features::InvoiceFeatures;
5693+
use crate::routing::gossip::NetworkGraph;
5694+
use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters};
5695+
use crate::util::config::UserConfig;
5696+
use crate::util::logger::{Logger, Record};
5697+
use crate::util::ser::ReadableArgs;
5698+
5699+
use test::Bencher;
5700+
5701+
struct DummyLogger {}
5702+
impl Logger for DummyLogger {
5703+
fn log(&self, _record: &Record) {}
5704+
}
5705+
5706+
fn read_network_graph(logger: &DummyLogger) -> NetworkGraph<&DummyLogger> {
5707+
let mut d = bench_utils::get_route_file().unwrap();
5708+
NetworkGraph::read(&mut d, logger).unwrap()
5709+
}
5710+
5711+
fn payer_pubkey() -> PublicKey {
5712+
let secp_ctx = Secp256k1::new();
5713+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
5714+
}
57075715

57085716
#[bench]
57095717
fn generate_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
@@ -5759,7 +5767,7 @@ mod benches {
57595767
seed *= 0xdeadbeef;
57605768
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
57615769
let params = PaymentParameters::from_node_id(dst, 42).with_features(features.clone());
5762-
let first_hop = first_hop(src);
5770+
let first_hop = bench_utils::first_hop(src);
57635771
let amt = seed as u64 % 1_000_000;
57645772
if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, 42, &DummyLogger{}, &scorer, &random_seed_bytes) {
57655773
routes.push(route);

0 commit comments

Comments
 (0)