@@ -783,6 +783,7 @@ impl ProbabilisticScoringDecayParameters {
783
783
/// Direction is defined in terms of [`NodeId`] partial ordering, where the source node is the
784
784
/// first node in the ordering of the channel's counterparties. Thus, swapping the two liquidity
785
785
/// offset fields gives the opposite direction.
786
+ #[ repr( C ) ] // Force the fields in memory to be in the order we specify
786
787
struct ChannelLiquidity {
787
788
/// Lower channel liquidity bound in terms of an offset from zero.
788
789
min_liquidity_offset_msat : u64 ,
@@ -800,6 +801,16 @@ struct ChannelLiquidity {
800
801
offset_history_last_updated : Duration ,
801
802
}
802
803
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
+
803
814
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity.
804
815
struct DirectedChannelLiquidity < L : Deref < Target = u64 > , HT : Deref < Target = HistoricalLiquidityTracker > , T : Deref < Target = Duration > > {
805
816
min_liquidity_offset_msat : L ,
@@ -1490,10 +1501,24 @@ mod bucketed_history {
1490
1501
// between the 12,000th sat and 24,000th sat, while only needing to store and operate on 32
1491
1502
// buckets in total.
1492
1503
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 ( ) ;
1497
1522
1498
1523
const LEGACY_TO_BUCKET_RANGE : [ ( u8 , u8 ) ; 8 ] = [
1499
1524
( 0 , 12 ) , ( 12 , 14 ) , ( 14 , 15 ) , ( 15 , 16 ) , ( 16 , 17 ) , ( 17 , 18 ) , ( 18 , 20 ) , ( 20 , 32 )
@@ -1631,10 +1656,19 @@ mod bucketed_history {
1631
1656
impl_writeable_tlv_based ! ( LegacyHistoricalBucketRangeTracker , { ( 0 , buckets, required) } ) ;
1632
1657
1633
1658
#[ derive( Clone , Copy ) ]
1659
+ #[ repr( C ) ] // Force the fields in memory to be in the order we specify.
1634
1660
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 ,
1635
1670
min_liquidity_offset_history : HistoricalBucketRangeTracker ,
1636
1671
max_liquidity_offset_history : HistoricalBucketRangeTracker ,
1637
- total_valid_points_tracked : u64 ,
1638
1672
}
1639
1673
1640
1674
impl HistoricalLiquidityTracker {
0 commit comments