Skip to content

Commit 18c0b5d

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 2d6720e commit 18c0b5d

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
@@ -771,6 +771,19 @@ impl ProbabilisticScoringDecayParameters {
771771
}
772772
}
773773

774+
/// A dummy copy of [`ChannelLiquidity`] to calculate its unpadded size
775+
#[repr(C)]
776+
struct DummyLiquidity {
777+
a: u64,
778+
b: u64,
779+
c: HistoricalLiquidityTracker,
780+
d: Duration,
781+
e: Duration,
782+
}
783+
784+
/// The amount of padding required to make [`ChannelLiquidity`] (plus a u64) a full 4 cache lines.
785+
const LIQ_PADDING_LEN: usize = (256 - ::core::mem::size_of::<(u64, DummyLiquidity)>()) / 8;
786+
774787
/// Accounting for channel liquidity balance uncertainty.
775788
///
776789
/// Direction is defined in terms of [`NodeId`] partial ordering, where the source node is the
@@ -792,17 +805,25 @@ struct ChannelLiquidity {
792805
/// Time when the historical liquidity bounds were last modified as an offset against the unix
793806
/// epoch.
794807
offset_history_last_updated: Duration,
808+
809+
_padding: [u64; LIQ_PADDING_LEN],
795810
}
796811

797-
// Check that the liquidity HashMap's entries sit on round cache lines.
812+
// Check that the liquidity HashMap's entries sit on round cache line pairs.
813+
//
814+
// Most modern CPUs have 64-byte cache lines, so we really want to be on round cache lines to avoid
815+
// hitting memory too much during scoring. Further, many x86 CPUs (and possibly others) load
816+
// adjacent cache lines opportunistically in case they will be useful.
798817
//
799-
// Specifically, the first cache line will have the key, the liquidity offsets, and the total
800-
// points tracked in the historical tracker.
818+
// Thus, we really want our HashMap entries to be aligned to 128 bytes. This will leave the first
819+
// cache line will have the key, the liquidity offsets, and the total points tracked in the
820+
// historical tracker.
801821
//
802822
// The next two cache lines will have the historical points, which we only access last during
803-
// scoring, followed by the last_updated `Duration`s (which we do not need during scoring).
804-
const _LIQUIDITY_MAP_SIZING_CHECK: usize = 192 - ::core::mem::size_of::<(u64, ChannelLiquidity)>();
805-
const _LIQUIDITY_MAP_SIZING_CHECK_2: usize = ::core::mem::size_of::<(u64, ChannelLiquidity)>() - 192;
823+
// scoring, followed by the last_updated `Duration`s (which we do not need during scoring). The
824+
// extra padding brings us up to a clean four cache lines.
825+
const _LIQUIDITY_MAP_SIZING_CHECK: usize = 256 - ::core::mem::size_of::<(u64, ChannelLiquidity)>();
826+
const _LIQUIDITY_MAP_SIZING_CHECK_2: usize = ::core::mem::size_of::<(u64, ChannelLiquidity)>() - 256;
806827

807828
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity.
808829
struct DirectedChannelLiquidity<L: Deref<Target = u64>, HT: Deref<Target = HistoricalLiquidityTracker>, T: Deref<Target = Duration>> {
@@ -988,6 +1009,7 @@ impl ChannelLiquidity {
9881009
liquidity_history: HistoricalLiquidityTracker::new(),
9891010
last_updated,
9901011
offset_history_last_updated: last_updated,
1012+
_padding: [0; LIQ_PADDING_LEN],
9911013
}
9921014
}
9931015

@@ -1980,13 +2002,14 @@ impl Readable for ChannelLiquidity {
19802002
),
19812003
last_updated,
19822004
offset_history_last_updated: offset_history_last_updated.unwrap_or(last_updated),
2005+
_padding: [0; LIQ_PADDING_LEN],
19832006
})
19842007
}
19852008
}
19862009

19872010
#[cfg(test)]
19882011
mod tests {
1989-
use super::{ChannelLiquidity, HistoricalLiquidityTracker, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters, ProbabilisticScorer};
2012+
use super::*;
19902013
use crate::blinded_path::BlindedHop;
19912014
use crate::util::config::UserConfig;
19922015

@@ -2160,12 +2183,14 @@ mod tests {
21602183
min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100,
21612184
last_updated, offset_history_last_updated,
21622185
liquidity_history: HistoricalLiquidityTracker::new(),
2186+
_padding: [0; LIQ_PADDING_LEN],
21632187
})
21642188
.with_channel(43,
21652189
ChannelLiquidity {
21662190
min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100,
21672191
last_updated, offset_history_last_updated,
21682192
liquidity_history: HistoricalLiquidityTracker::new(),
2193+
_padding: [0; LIQ_PADDING_LEN],
21692194
});
21702195
let source = source_node_id();
21712196
let target = target_node_id();
@@ -2239,6 +2264,7 @@ mod tests {
22392264
min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400,
22402265
last_updated, offset_history_last_updated,
22412266
liquidity_history: HistoricalLiquidityTracker::new(),
2267+
_padding: [0; LIQ_PADDING_LEN],
22422268
});
22432269
let source = source_node_id();
22442270
let target = target_node_id();
@@ -2299,6 +2325,7 @@ mod tests {
22992325
min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400,
23002326
last_updated, offset_history_last_updated,
23012327
liquidity_history: HistoricalLiquidityTracker::new(),
2328+
_padding: [0; LIQ_PADDING_LEN],
23022329
});
23032330
let source = source_node_id();
23042331
let target = target_node_id();
@@ -2418,6 +2445,7 @@ mod tests {
24182445
min_liquidity_offset_msat: 40, max_liquidity_offset_msat: 40,
24192446
last_updated, offset_history_last_updated,
24202447
liquidity_history: HistoricalLiquidityTracker::new(),
2448+
_padding: [0; LIQ_PADDING_LEN],
24212449
});
24222450
let source = source_node_id();
24232451

0 commit comments

Comments
 (0)