@@ -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.
917938struct 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) ]
24392462mod 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