Skip to content

Commit 6680b97

Browse files
committed
Manually lay out scorer memory
1 parent c4df3c3 commit 6680b97

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

lightning/src/routing/scoring.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ impl ProbabilisticScoringDecayParameters {
783783
/// Direction is defined in terms of [`NodeId`] partial ordering, where the source node is the
784784
/// first node in the ordering of the channel's counterparties. Thus, swapping the two liquidity
785785
/// offset fields gives the opposite direction.
786+
#[repr(C)] // Force the fields in memory to be in the order we specify
786787
struct ChannelLiquidity {
787788
/// Lower channel liquidity bound in terms of an offset from zero.
788789
min_liquidity_offset_msat: u64,
@@ -800,6 +801,16 @@ struct ChannelLiquidity {
800801
offset_history_last_updated: Duration,
801802
}
802803

804+
// Check that the liquidity HashMap's entries sit on round cache lines.
805+
//
806+
// Specifically, the first cache line will have the key, the liquidity offsets, and the total
807+
// points tracked in the historical tracker.
808+
//
809+
// The next two cache lines will have the historical points, which we only access last during
810+
// scoring, followed by the last_updated `Duration`s (which we do not need during scoring).
811+
const _LIQUIDITY_MAP_SIZING_CHECK: usize = 192 - ::core::mem::size_of::<(u64, ChannelLiquidity)>();
812+
const _LIQUIDITY_MAP_SIZING_CHECK_2: usize = ::core::mem::size_of::<(u64, ChannelLiquidity)>() - 192;
813+
803814
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity.
804815
struct DirectedChannelLiquidity<L: Deref<Target = u64>, HT: Deref<Target = HistoricalLiquidityTracker>, T: Deref<Target = Duration>> {
805816
min_liquidity_offset_msat: L,
@@ -1490,10 +1501,24 @@ mod bucketed_history {
14901501
// between the 12,000th sat and 24,000th sat, while only needing to store and operate on 32
14911502
// buckets in total.
14921503

1493-
const BUCKET_START_POS: [u16; 33] = [
1494-
0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096, 6144, 8192, 10240, 12288,
1495-
13312, 14336, 15360, 15872, 16128, 16256, 16320, 16352, 16368, 16376, 16380, 16382, 16383, 16384,
1496-
];
1504+
// By default u16s may not be cache-aligned, but we'd rather not have to read a third cache
1505+
// line just to access it
1506+
#[repr(align(128))]
1507+
struct BucketStartPos([u16; 33]);
1508+
impl BucketStartPos {
1509+
const fn new() -> Self {
1510+
Self([
1511+
0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096, 6144, 8192, 10240, 12288,
1512+
13312, 14336, 15360, 15872, 16128, 16256, 16320, 16352, 16368, 16376, 16380, 16382, 16383, 16384,
1513+
])
1514+
}
1515+
}
1516+
impl core::ops::Index<usize> for BucketStartPos {
1517+
type Output = u16;
1518+
#[inline(always)]
1519+
fn index(&self, index: usize) -> &u16 { &self.0[index] }
1520+
}
1521+
const BUCKET_START_POS: BucketStartPos = BucketStartPos::new();
14971522

14981523
const LEGACY_TO_BUCKET_RANGE: [(u8, u8); 8] = [
14991524
(0, 12), (12, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 20), (20, 32)
@@ -1631,10 +1656,19 @@ mod bucketed_history {
16311656
impl_writeable_tlv_based!(LegacyHistoricalBucketRangeTracker, { (0, buckets, required) });
16321657

16331658
#[derive(Clone, Copy)]
1659+
#[repr(C)] // Force the fields in memory to be in the order we specify.
16341660
pub(super) struct HistoricalLiquidityTracker {
1661+
// This struct sits inside a `(u64, ChannelLiquidity)` in memory, and we first read the
1662+
// liquidity offsets in `ChannelLiquidity` when calculating the non-historical score. This
1663+
// means that the first handful of bytes of this struct will already be sitting in cache by
1664+
// the time we go to look at them.
1665+
//
1666+
// Because the first thing we do is check if `total_valid_points` is sufficient to consider
1667+
// the data here at all, and can return early if it is not, we want this to go first to
1668+
// avoid hitting a second cache line load entirely in that case.
1669+
total_valid_points_tracked: u64,
16351670
min_liquidity_offset_history: HistoricalBucketRangeTracker,
16361671
max_liquidity_offset_history: HistoricalBucketRangeTracker,
1637-
total_valid_points_tracked: u64,
16381672
}
16391673

16401674
impl HistoricalLiquidityTracker {

0 commit comments

Comments
 (0)