Skip to content

Commit fbaa3c4

Browse files
committed
Unify route benchmarking with route tests
There's a few route tests which do the same thing as the benchmarks as they're also a good test. However, they didn't share code, which is somewhat wasteful, so we fix that here.
1 parent e61b128 commit fbaa3c4

File tree

1 file changed

+119
-128
lines changed

1 file changed

+119
-128
lines changed

lightning/src/routing/router.rs

Lines changed: 119 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -5791,82 +5791,47 @@ mod tests {
57915791
println!("Using seed of {}", seed);
57925792
seed
57935793
}
5794-
#[cfg(not(feature = "no-std"))]
5795-
use crate::util::ser::ReadableArgs;
57965794

57975795
#[test]
57985796
#[cfg(not(feature = "no-std"))]
57995797
fn generate_routes() {
58005798
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
58015799

5802-
let mut d = match super::bench_utils::get_route_file() {
5800+
let logger = ln_test_utils::TestLogger::new();
5801+
let graph = match super::bench_utils::read_network_graph(&logger) {
58035802
Ok(f) => f,
58045803
Err(e) => {
58055804
eprintln!("{}", e);
58065805
return;
58075806
},
58085807
};
5809-
let logger = ln_test_utils::TestLogger::new();
5810-
let graph = NetworkGraph::read(&mut d, &logger).unwrap();
5811-
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
5812-
let random_seed_bytes = keys_manager.get_secure_random_bytes();
58135808

5814-
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
5815-
let mut seed = random_init_seed() as usize;
5816-
let nodes = graph.read_only().nodes().clone();
5817-
'load_endpoints: for _ in 0..10 {
5818-
loop {
5819-
seed = seed.overflowing_mul(0xdeadbeef).0;
5820-
let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
5821-
seed = seed.overflowing_mul(0xdeadbeef).0;
5822-
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
5823-
let payment_params = PaymentParameters::from_node_id(dst, 42);
5824-
let amt = seed as u64 % 200_000_000;
5825-
let params = ProbabilisticScoringFeeParameters::default();
5826-
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
5827-
if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &params, &random_seed_bytes).is_ok() {
5828-
continue 'load_endpoints;
5829-
}
5830-
}
5831-
}
5809+
let params = ProbabilisticScoringFeeParameters::default();
5810+
let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
5811+
let features = super::InvoiceFeatures::empty();
5812+
5813+
super::bench_utils::generate_test_routes(&graph, &mut scorer, &params, features, random_init_seed() as usize, 2);
58325814
}
58335815

58345816
#[test]
58355817
#[cfg(not(feature = "no-std"))]
58365818
fn generate_routes_mpp() {
58375819
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
58385820

5839-
let mut d = match super::bench_utils::get_route_file() {
5821+
let logger = ln_test_utils::TestLogger::new();
5822+
let graph = match super::bench_utils::read_network_graph(&logger) {
58405823
Ok(f) => f,
58415824
Err(e) => {
58425825
eprintln!("{}", e);
58435826
return;
58445827
},
58455828
};
5846-
let logger = ln_test_utils::TestLogger::new();
5847-
let graph = NetworkGraph::read(&mut d, &logger).unwrap();
5848-
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
5849-
let random_seed_bytes = keys_manager.get_secure_random_bytes();
5850-
let config = UserConfig::default();
58515829

5852-
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
5853-
let mut seed = random_init_seed() as usize;
5854-
let nodes = graph.read_only().nodes().clone();
5855-
'load_endpoints: for _ in 0..10 {
5856-
loop {
5857-
seed = seed.overflowing_mul(0xdeadbeef).0;
5858-
let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
5859-
seed = seed.overflowing_mul(0xdeadbeef).0;
5860-
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
5861-
let payment_params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
5862-
let amt = seed as u64 % 200_000_000;
5863-
let params = ProbabilisticScoringFeeParameters::default();
5864-
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
5865-
if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &params, &random_seed_bytes).is_ok() {
5866-
continue 'load_endpoints;
5867-
}
5868-
}
5869-
}
5830+
let params = ProbabilisticScoringFeeParameters::default();
5831+
let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
5832+
let features = channelmanager::provided_invoice_features(&UserConfig::default());
5833+
5834+
super::bench_utils::generate_test_routes(&graph, &mut scorer, &params, features, random_init_seed() as usize, 2);
58705835
}
58715836

58725837
#[test]
@@ -6054,7 +6019,21 @@ mod tests {
60546019

60556020
#[cfg(all(test, not(feature = "no-std")))]
60566021
pub(crate) mod bench_utils {
6022+
use super::*;
60576023
use std::fs::File;
6024+
6025+
use bitcoin::hashes::Hash;
6026+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
6027+
6028+
use crate::chain::transaction::OutPoint;
6029+
use crate::sign::{EntropySource, KeysManager};
6030+
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
6031+
use crate::ln::features::InvoiceFeatures;
6032+
use crate::routing::gossip::NetworkGraph;
6033+
use crate::util::config::UserConfig;
6034+
use crate::util::ser::ReadableArgs;
6035+
use crate::util::test_utils::TestLogger;
6036+
60586037
/// Tries to open a network graph file, or panics with a URL to fetch it.
60596038
pub(crate) fn get_route_file() -> Result<std::fs::File, &'static str> {
60606039
let res = File::open("net_graph-2023-01-18.bin") // By default we're run in RL/lightning
@@ -6077,42 +6056,18 @@ pub(crate) mod bench_utils {
60776056
#[cfg(not(require_route_graph_test))]
60786057
return res;
60796058
}
6080-
}
6081-
6082-
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
6083-
mod benches {
6084-
use super::*;
6085-
use bitcoin::hashes::Hash;
6086-
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
6087-
use crate::chain::transaction::OutPoint;
6088-
use crate::sign::{EntropySource, KeysManager};
6089-
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
6090-
use crate::ln::features::InvoiceFeatures;
6091-
use crate::routing::gossip::NetworkGraph;
6092-
use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
6093-
use crate::util::config::UserConfig;
6094-
use crate::util::logger::{Logger, Record};
6095-
use crate::util::ser::ReadableArgs;
6096-
6097-
use test::Bencher;
6098-
6099-
struct DummyLogger {}
6100-
impl Logger for DummyLogger {
6101-
fn log(&self, _record: &Record) {}
6102-
}
61036059

6104-
fn read_network_graph(logger: &DummyLogger) -> NetworkGraph<&DummyLogger> {
6105-
let mut d = bench_utils::get_route_file().unwrap();
6106-
NetworkGraph::read(&mut d, logger).unwrap()
6060+
pub(crate) fn read_network_graph(logger: &TestLogger) -> Result<NetworkGraph<&TestLogger>, &'static str> {
6061+
get_route_file().map(|mut f| NetworkGraph::read(&mut f, logger).unwrap())
61076062
}
61086063

6109-
fn payer_pubkey() -> PublicKey {
6064+
pub(crate) fn payer_pubkey() -> PublicKey {
61106065
let secp_ctx = Secp256k1::new();
61116066
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
61126067
}
61136068

61146069
#[inline]
6115-
fn first_hop(node_id: PublicKey) -> ChannelDetails {
6070+
pub(crate) fn first_hop(node_id: PublicKey) -> ChannelDetails {
61166071
ChannelDetails {
61176072
channel_id: [0; 32],
61186073
counterparty: ChannelCounterparty {
@@ -6151,63 +6106,29 @@ mod benches {
61516106
}
61526107
}
61536108

6154-
#[bench]
6155-
fn generate_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
6156-
let logger = DummyLogger {};
6157-
let network_graph = read_network_graph(&logger);
6158-
let scorer = FixedPenaltyScorer::with_penalty(0);
6159-
generate_routes(bench, &network_graph, scorer, &(), InvoiceFeatures::empty());
6160-
}
6161-
6162-
#[bench]
6163-
fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
6164-
let logger = DummyLogger {};
6165-
let network_graph = read_network_graph(&logger);
6166-
let scorer = FixedPenaltyScorer::with_penalty(0);
6167-
generate_routes(bench, &network_graph, scorer, &(), channelmanager::provided_invoice_features(&UserConfig::default()));
6168-
}
6169-
6170-
#[bench]
6171-
fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6172-
let logger = DummyLogger {};
6173-
let network_graph = read_network_graph(&logger);
6174-
let params = ProbabilisticScoringFeeParameters::default();
6175-
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
6176-
generate_routes(bench, &network_graph, scorer, &params, InvoiceFeatures::empty());
6177-
}
6178-
6179-
#[bench]
6180-
fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6181-
let logger = DummyLogger {};
6182-
let network_graph = read_network_graph(&logger);
6183-
let params = ProbabilisticScoringFeeParameters::default();
6184-
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
6185-
generate_routes(bench, &network_graph, scorer, &params, channelmanager::provided_invoice_features(&UserConfig::default()));
6186-
}
6187-
6188-
fn generate_routes<S: Score>(
6189-
bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S, score_params: &S::ScoreParams,
6190-
features: InvoiceFeatures
6191-
) {
6192-
let nodes = graph.read_only().nodes().clone();
6109+
pub(crate) fn generate_test_routes<S: Score>(graph: &NetworkGraph<&TestLogger>, scorer: &mut S,
6110+
score_params: &S::ScoreParams, features: InvoiceFeatures, mut seed: usize, route_count: usize,
6111+
) -> Vec<(ChannelDetails, PaymentParameters, u64)> {
61936112
let payer = payer_pubkey();
61946113
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
61956114
let random_seed_bytes = keys_manager.get_secure_random_bytes();
61966115

6197-
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
6198-
let mut routes = Vec::new();
6116+
let nodes = graph.read_only().nodes().clone();
61996117
let mut route_endpoints = Vec::new();
6200-
let mut seed: usize = 0xdeadbeef;
6201-
'load_endpoints: for _ in 0..150 {
6118+
let mut routes = Vec::new();
6119+
6120+
'load_endpoints: for _ in 0..route_count * 3 /2 {
62026121
loop {
6203-
seed *= 0xdeadbeef;
6122+
seed = seed.overflowing_mul(0xdeadbeef).0;
62046123
let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
6205-
seed *= 0xdeadbeef;
6124+
seed = seed.overflowing_mul(0xdeadbeef).0;
62066125
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
62076126
let params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(features.clone()).unwrap();
62086127
let first_hop = first_hop(src);
62096128
let amt = seed as u64 % 1_000_000;
6210-
if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes) {
6129+
if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]),
6130+
amt, &TestLogger::new(), &scorer, score_params, &random_seed_bytes,
6131+
) {
62116132
routes.push(route);
62126133
route_endpoints.push((first_hop, params, amt));
62136134
continue 'load_endpoints;
@@ -6230,20 +6151,90 @@ mod benches {
62306151
}
62316152
}
62326153

6233-
// Because we've changed channel scores, its possible we'll take different routes to the
6154+
// Because we've changed channel scores, it's possible we'll take different routes to the
62346155
// selected destinations, possibly causing us to fail because, eg, the newly-selected path
62356156
// requires a too-high CLTV delta.
62366157
route_endpoints.retain(|(first_hop, params, amt)| {
6237-
get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok()
6158+
get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt,
6159+
&TestLogger::new(), &scorer, score_params, &random_seed_bytes).is_ok()
62386160
});
6239-
route_endpoints.truncate(100);
6240-
assert_eq!(route_endpoints.len(), 100);
6161+
route_endpoints.truncate(route_count);
6162+
assert_eq!(route_endpoints.len(), route_count);
6163+
route_endpoints
6164+
}
6165+
}
6166+
6167+
#[cfg(all(test, feature = "_bench_unstable", not(feature = "no-std")))]
6168+
mod benches {
6169+
use super::*;
6170+
use crate::sign::{EntropySource, KeysManager};
6171+
use crate::ln::channelmanager;
6172+
use crate::ln::features::InvoiceFeatures;
6173+
use crate::routing::gossip::NetworkGraph;
6174+
use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
6175+
use crate::util::config::UserConfig;
6176+
use crate::util::logger::{Logger, Record};
6177+
use crate::util::test_utils::TestLogger;
6178+
6179+
use test::Bencher;
6180+
6181+
struct DummyLogger {}
6182+
impl Logger for DummyLogger {
6183+
fn log(&self, _record: &Record) {}
6184+
}
6185+
6186+
6187+
#[bench]
6188+
fn generate_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
6189+
let logger = TestLogger::new();
6190+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6191+
let scorer = FixedPenaltyScorer::with_penalty(0);
6192+
generate_routes(bench, &network_graph, scorer, &(), InvoiceFeatures::empty());
6193+
}
6194+
6195+
#[bench]
6196+
fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
6197+
let logger = TestLogger::new();
6198+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6199+
let scorer = FixedPenaltyScorer::with_penalty(0);
6200+
generate_routes(bench, &network_graph, scorer, &(), channelmanager::provided_invoice_features(&UserConfig::default()));
6201+
}
6202+
6203+
#[bench]
6204+
fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6205+
let logger = TestLogger::new();
6206+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6207+
let params = ProbabilisticScoringFeeParameters::default();
6208+
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
6209+
generate_routes(bench, &network_graph, scorer, &params, InvoiceFeatures::empty());
6210+
}
6211+
6212+
#[bench]
6213+
fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6214+
let logger = TestLogger::new();
6215+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6216+
let params = ProbabilisticScoringFeeParameters::default();
6217+
let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
6218+
generate_routes(bench, &network_graph, scorer, &params, channelmanager::provided_invoice_features(&UserConfig::default()));
6219+
}
6220+
6221+
fn generate_routes<S: Score>(
6222+
bench: &mut Bencher, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
6223+
score_params: &S::ScoreParams, features: InvoiceFeatures,
6224+
) {
6225+
let payer = bench_utils::payer_pubkey();
6226+
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
6227+
let random_seed_bytes = keys_manager.get_secure_random_bytes();
6228+
6229+
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
6230+
let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, score_params, features, 0xdeadbeef, 100);
62416231

62426232
// ...then benchmark finding paths between the nodes we learned.
62436233
let mut idx = 0;
62446234
bench.iter(|| {
62456235
let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
6246-
assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
6236+
assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt,
6237+
&DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
62476238
idx += 1;
62486239
});
62496240
}

0 commit comments

Comments
 (0)