Skip to content

Commit 46bf812

Browse files
committed
Calculate the padding required on ChannelLiquidity dynamically
We expect `ChannelLiquidity` to be exactly three cache lines to ensure the first bytes we need are all one one cache line, but in practice its a bit more ideal for `ChannelLiquidity`s to always start on an even cache line as x86 CPUs will often load the neighboring cache line automatically. Further, it looks like some versions of `rustc` on some platforms don't pack `ChannelLiquidity` as well (in #3415) and the next commit is going to push us over three cache lines anyway. Instead, here we calculate out the proper padding for `ChannelLiquidity` to make it align to four 64-byte cache lines. Should fix #3415.
1 parent 1b281f1 commit 46bf812

File tree

1 file changed

+35
-7
lines changed

1 file changed

+35
-7
lines changed

lightning/src/routing/scoring.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,19 @@ impl ProbabilisticScoringDecayParameters {
879879
}
880880
}
881881

882+
/// A dummy copy of [`ChannelLiquidity`] to calculate its unpadded size
883+
#[repr(C)]
884+
struct DummyLiquidity {
885+
a: u64,
886+
b: u64,
887+
c: HistoricalLiquidityTracker,
888+
d: Duration,
889+
e: Duration,
890+
}
891+
892+
/// The amount of padding required to make [`ChannelLiquidity`] (plus a u64) a full 4 cache lines.
893+
const LIQ_PADDING_LEN: usize = (256 - ::core::mem::size_of::<(u64, DummyLiquidity)>()) / 8;
894+
882895
/// Accounting for channel liquidity balance uncertainty.
883896
///
884897
/// Direction is defined in terms of [`NodeId`] partial ordering, where the source node is the
@@ -901,17 +914,25 @@ struct ChannelLiquidity {
901914
/// Time when the historical liquidity bounds were last modified as an offset against the unix
902915
/// epoch.
903916
offset_history_last_updated: Duration,
917+
918+
_padding: [u64; LIQ_PADDING_LEN],
904919
}
905920

906-
// Check that the liquidity HashMap's entries sit on round cache lines.
921+
// Check that the liquidity HashMap's entries sit on round cache line pairs.
922+
//
923+
// Most modern CPUs have 64-byte cache lines, so we really want to be on round cache lines to avoid
924+
// hitting memory too much during scoring. Further, many x86 CPUs (and possibly others) load
925+
// adjacent cache lines opportunistically in case they will be useful.
907926
//
908-
// Specifically, the first cache line will have the key, the liquidity offsets, and the total
909-
// points tracked in the historical tracker.
927+
// Thus, we really want our HashMap entries to be aligned to 128 bytes. This will leave the first
928+
// cache line will have the key, the liquidity offsets, and the total points tracked in the
929+
// historical tracker.
910930
//
911931
// The next two cache lines will have the historical points, which we only access last during
912-
// scoring, followed by the last_updated `Duration`s (which we do not need during scoring).
913-
const _LIQUIDITY_MAP_SIZING_CHECK: usize = 192 - ::core::mem::size_of::<(u64, ChannelLiquidity)>();
914-
const _LIQUIDITY_MAP_SIZING_CHECK_2: usize = ::core::mem::size_of::<(u64, ChannelLiquidity)>() - 192;
932+
// scoring, followed by the last_updated `Duration`s (which we do not need during scoring). The
933+
// extra padding brings us up to a clean four cache lines.
934+
const _LIQUIDITY_MAP_SIZING_CHECK: usize = 256 - ::core::mem::size_of::<(u64, ChannelLiquidity)>();
935+
const _LIQUIDITY_MAP_SIZING_CHECK_2: usize = ::core::mem::size_of::<(u64, ChannelLiquidity)>() - 256;
915936

916937
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity.
917938
struct DirectedChannelLiquidity<L: Deref<Target = u64>, HT: Deref<Target = HistoricalLiquidityTracker>, T: Deref<Target = Duration>> {
@@ -1163,6 +1184,7 @@ impl ChannelLiquidity {
11631184
liquidity_history: HistoricalLiquidityTracker::new(),
11641185
last_updated,
11651186
offset_history_last_updated: last_updated,
1187+
_padding: [0; LIQ_PADDING_LEN],
11661188
}
11671189
}
11681190

@@ -2431,13 +2453,14 @@ impl Readable for ChannelLiquidity {
24312453
),
24322454
last_updated,
24332455
offset_history_last_updated: offset_history_last_updated.unwrap_or(last_updated),
2456+
_padding: [0; LIQ_PADDING_LEN],
24342457
})
24352458
}
24362459
}
24372460

24382461
#[cfg(test)]
24392462
mod tests {
2440-
use super::{ChannelLiquidity, HistoricalLiquidityTracker, ProbabilisticScorer, ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters};
2463+
use super::*;
24412464
use crate::blinded_path::BlindedHop;
24422465
use crate::util::config::UserConfig;
24432466

@@ -2612,12 +2635,14 @@ mod tests {
26122635
min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100,
26132636
last_updated, offset_history_last_updated,
26142637
liquidity_history: HistoricalLiquidityTracker::new(),
2638+
_padding: [0; LIQ_PADDING_LEN],
26152639
})
26162640
.with_channel(43,
26172641
ChannelLiquidity {
26182642
min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100,
26192643
last_updated, offset_history_last_updated,
26202644
liquidity_history: HistoricalLiquidityTracker::new(),
2645+
_padding: [0; LIQ_PADDING_LEN],
26212646
});
26222647
let source = source_node_id();
26232648
let target = target_node_id();
@@ -2691,6 +2716,7 @@ mod tests {
26912716
min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400,
26922717
last_updated, offset_history_last_updated,
26932718
liquidity_history: HistoricalLiquidityTracker::new(),
2719+
_padding: [0; LIQ_PADDING_LEN],
26942720
});
26952721
let source = source_node_id();
26962722
let target = target_node_id();
@@ -2751,6 +2777,7 @@ mod tests {
27512777
min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400,
27522778
last_updated, offset_history_last_updated,
27532779
liquidity_history: HistoricalLiquidityTracker::new(),
2780+
_padding: [0; LIQ_PADDING_LEN],
27542781
});
27552782
let source = source_node_id();
27562783
let target = target_node_id();
@@ -2870,6 +2897,7 @@ mod tests {
28702897
min_liquidity_offset_msat: 40, max_liquidity_offset_msat: 40,
28712898
last_updated, offset_history_last_updated,
28722899
liquidity_history: HistoricalLiquidityTracker::new(),
2900+
_padding: [0; LIQ_PADDING_LEN],
28732901
});
28742902
let source = source_node_id();
28752903

0 commit comments

Comments
 (0)