Skip to content

Commit a437b77

Browse files
committed
Skip storing an explicit node_id in RouteGraphNode
`RouteGraphNode` is the main heap entry in our dijkstra's next-best heap. Thus, because its rather constantly being sorted, we care a good bit about its size as fitting more of them on a cache line can provide some additional speed. In 43d250d, we switched from tracking nodes during pathfinding by their `NodeId` to a "counter" which allows us to avoid `HashMap`s lookups for much of the pathfinding process. Because the `dist` lookup is now quite cheap (its just a `Vec`), there's no reason to track `NodeId`s in the heap entries. Instead, we simply fetch the `NodeId` of the node via the `dist` map by examining its `candidate`'s pointer to its source `NodeId`. This allows us to remove a `NodeId` in `RouteGraphNode`, moving it from 64 to 32 bytes. This allows us to expand the `score` field size in a coming commit without expanding `RouteGraphNode`'s size. While we were doing the `dist` lookup in `add_entries_to_cheapest_to_target_node` anyway, the `NodeId` lookup via the `candidate` may not be free. Still, avoiding expanding `RouteGraphNode` above 128 bytes in a few commits is a nice win.
1 parent 0fe51c5 commit a437b77

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

lightning/src/routing/router.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,9 +1393,8 @@ impl_writeable_tlv_based!(RouteHintHop, {
13931393
});
13941394

13951395
#[derive(Eq, PartialEq)]
1396-
#[repr(align(64))] // Force the size to 64 bytes
1396+
#[repr(align(32))] // Force the size to 32 bytes
13971397
struct RouteGraphNode {
1398-
node_id: NodeId,
13991398
node_counter: u32,
14001399
score: u64,
14011400
// The maximum value a yet-to-be-constructed payment path might flow through this node.
@@ -1426,9 +1425,8 @@ impl cmp::PartialOrd for RouteGraphNode {
14261425
}
14271426

14281427
// While RouteGraphNode can be laid out with fewer bytes, performance appears to be improved
1429-
// substantially when it is laid out at exactly 64 bytes.
1430-
const _GRAPH_NODE_SMALL: usize = 64 - core::mem::size_of::<RouteGraphNode>();
1431-
const _GRAPH_NODE_FIXED_SIZE: usize = core::mem::size_of::<RouteGraphNode>() - 64;
1428+
// substantially when it is laid out at exactly 32 bytes.
1429+
const _GRAPH_NODE_32: () = assert!(core::mem::size_of::<RouteGraphNode>() == 32);
14321430

14331431
/// A [`CandidateRouteHop::FirstHop`] entry.
14341432
#[derive(Clone, Debug)]
@@ -3004,7 +3002,6 @@ where L::Target: Logger {
30043002
}
30053003

30063004
let new_graph_node = RouteGraphNode {
3007-
node_id: src_node_id,
30083005
node_counter: src_node_counter,
30093006
score: cmp::max(total_fee_msat, path_htlc_minimum_msat).saturating_add(path_penalty_msat),
30103007
total_cltv_delta: hop_total_cltv_delta,
@@ -3082,7 +3079,7 @@ where L::Target: Logger {
30823079
// This data can later be helpful to optimize routing (pay lower fees).
30833080
#[rustfmt::skip]
30843081
macro_rules! add_entries_to_cheapest_to_target_node {
3085-
( $node: expr, $node_counter: expr, $node_id: expr, $next_hops_value_contribution: expr,
3082+
( $node_counter: expr, $node_id: expr, $next_hops_value_contribution: expr,
30863083
$next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => {
30873084
let fee_to_target_msat;
30883085
let next_hops_path_htlc_minimum_msat;
@@ -3138,7 +3135,7 @@ where L::Target: Logger {
31383135
}
31393136
}
31403137

3141-
if let Some(node) = $node {
3138+
if let Some(node) = network_nodes.get(&$node_id) {
31423139
let features = if let Some(node_info) = node.announcement_info.as_ref() {
31433140
&node_info.features()
31443141
} else {
@@ -3265,7 +3262,7 @@ where L::Target: Logger {
32653262
entry.value_contribution_msat = path_value_msat;
32663263
}
32673264
add_entries_to_cheapest_to_target_node!(
3268-
network_nodes.get(&payee), payee_node_counter, payee, path_value_msat, 0, 0
3265+
payee_node_counter, payee, path_value_msat, 0, 0
32693266
);
32703267
}
32713268

@@ -3340,11 +3337,11 @@ where L::Target: Logger {
33403337
// Both these cases (and other cases except reaching recommended_value_msat) mean that
33413338
// paths_collection will be stopped because found_new_path==false.
33423339
// This is not necessarily a routing failure.
3343-
'path_construction: while let Some(RouteGraphNode { node_id, node_counter, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() {
3340+
'path_construction: while let Some(RouteGraphNode { node_counter, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() {
33443341

33453342
// Since we're going payee-to-payer, hitting our node as a target means we should stop
33463343
// traversing the graph and arrange the path out of what we found.
3347-
if node_id == our_node_id {
3344+
if node_counter == payer_node_counter {
33483345
let mut new_entry = dist[payer_node_counter as usize].take().unwrap();
33493346
let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = vec!((new_entry.clone(), default_node_features.clone()));
33503347

@@ -3468,13 +3465,20 @@ where L::Target: Logger {
34683465
// If we found a path back to the payee, we shouldn't try to process it again. This is
34693466
// the equivalent of the `elem.was_processed` check in
34703467
// add_entries_to_cheapest_to_target_node!() (see comment there for more info).
3471-
if node_id == maybe_dummy_payee_node_id { continue 'path_construction; }
3468+
if node_counter == payee_node_counter { continue 'path_construction; }
3469+
3470+
let node_id = if let Some(entry) = &dist[node_counter as usize] {
3471+
entry.candidate.source()
3472+
} else {
3473+
debug_assert!(false, "Best nodes in the heap should have entries in dist");
3474+
continue 'path_construction;
3475+
};
34723476

34733477
// Otherwise, since the current target node is not us,
34743478
// keep "unrolling" the payment graph from payee to payer by
34753479
// finding a way to reach the current target from the payer side.
34763480
add_entries_to_cheapest_to_target_node!(
3477-
network_nodes.get(&node_id), node_counter, node_id,
3481+
node_counter, node_id,
34783482
value_contribution_msat,
34793483
total_cltv_delta, path_length_to_node
34803484
);

0 commit comments

Comments
 (0)