@@ -879,6 +879,19 @@ impl ProbabilisticScoringDecayParameters {
879
879
}
880
880
}
881
881
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
+
882
895
/// Accounting for channel liquidity balance uncertainty.
883
896
///
884
897
/// Direction is defined in terms of [`NodeId`] partial ordering, where the source node is the
@@ -901,17 +914,25 @@ struct ChannelLiquidity {
901
914
/// Time when the historical liquidity bounds were last modified as an offset against the unix
902
915
/// epoch.
903
916
offset_history_last_updated : Duration ,
917
+
918
+ _padding : [ u64 ; LIQ_PADDING_LEN ] ,
904
919
}
905
920
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.
907
926
//
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.
910
930
//
911
931
// 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 ;
915
936
916
937
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity.
917
938
struct DirectedChannelLiquidity < L : Deref < Target = u64 > , HT : Deref < Target = HistoricalLiquidityTracker > , T : Deref < Target = Duration > > {
@@ -1163,6 +1184,7 @@ impl ChannelLiquidity {
1163
1184
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
1164
1185
last_updated,
1165
1186
offset_history_last_updated : last_updated,
1187
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
1166
1188
}
1167
1189
}
1168
1190
@@ -2431,13 +2453,14 @@ impl Readable for ChannelLiquidity {
2431
2453
) ,
2432
2454
last_updated,
2433
2455
offset_history_last_updated : offset_history_last_updated. unwrap_or ( last_updated) ,
2456
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2434
2457
} )
2435
2458
}
2436
2459
}
2437
2460
2438
2461
#[ cfg( test) ]
2439
2462
mod tests {
2440
- use super :: { ChannelLiquidity , HistoricalLiquidityTracker , ProbabilisticScorer , ProbabilisticScoringDecayParameters , ProbabilisticScoringFeeParameters } ;
2463
+ use super :: * ;
2441
2464
use crate :: blinded_path:: BlindedHop ;
2442
2465
use crate :: util:: config:: UserConfig ;
2443
2466
@@ -2612,12 +2635,14 @@ mod tests {
2612
2635
min_liquidity_offset_msat : 700 , max_liquidity_offset_msat : 100 ,
2613
2636
last_updated, offset_history_last_updated,
2614
2637
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
2638
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2615
2639
} )
2616
2640
. with_channel ( 43 ,
2617
2641
ChannelLiquidity {
2618
2642
min_liquidity_offset_msat : 700 , max_liquidity_offset_msat : 100 ,
2619
2643
last_updated, offset_history_last_updated,
2620
2644
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
2645
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2621
2646
} ) ;
2622
2647
let source = source_node_id ( ) ;
2623
2648
let target = target_node_id ( ) ;
@@ -2691,6 +2716,7 @@ mod tests {
2691
2716
min_liquidity_offset_msat : 200 , max_liquidity_offset_msat : 400 ,
2692
2717
last_updated, offset_history_last_updated,
2693
2718
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
2719
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2694
2720
} ) ;
2695
2721
let source = source_node_id ( ) ;
2696
2722
let target = target_node_id ( ) ;
@@ -2751,6 +2777,7 @@ mod tests {
2751
2777
min_liquidity_offset_msat : 200 , max_liquidity_offset_msat : 400 ,
2752
2778
last_updated, offset_history_last_updated,
2753
2779
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
2780
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2754
2781
} ) ;
2755
2782
let source = source_node_id ( ) ;
2756
2783
let target = target_node_id ( ) ;
@@ -2870,6 +2897,7 @@ mod tests {
2870
2897
min_liquidity_offset_msat : 40 , max_liquidity_offset_msat : 40 ,
2871
2898
last_updated, offset_history_last_updated,
2872
2899
liquidity_history : HistoricalLiquidityTracker :: new ( ) ,
2900
+ _padding : [ 0 ; LIQ_PADDING_LEN ] ,
2873
2901
} ) ;
2874
2902
let source = source_node_id ( ) ;
2875
2903
0 commit comments