@@ -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.
808829struct 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) ]
19882011mod 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