@@ -18,29 +18,43 @@ FD_STATIC_ASSERT( FD_METRICS_ENUM_CRDS_VALUE_CNT==FD_GOSSIP_VALUE_LAST+1UL,
18
18
#define BLOOM_FALSE_POSITIVE_RATE (0.1)
19
19
#define BLOOM_NUM_KEYS (8.0)
20
20
21
- struct stake_weight {
22
- fd_pubkey_t key ;
21
+ struct stake {
22
+ fd_pubkey_t pubkey ;
23
23
ulong stake ;
24
- ulong hash ;
24
+
25
+ struct {
26
+ ulong prev ;
27
+ ulong next ;
28
+ } map ;
29
+
30
+ struct {
31
+ ulong next ;
32
+ } pool ;
25
33
};
26
34
27
- typedef struct stake_weight stake_weight_entry_t ;
35
+ typedef struct stake stake_t ;
28
36
29
- fd_pubkey_t pubkey_null = { .ul = {0UL ,0UL ,0UL ,0UL } };
37
+ /* NOTE: Since the staked count is known at the time we populate
38
+ the map, we can treat the pool as an array instead. This means we
39
+ can bypass the acquire/release model and quickly iterate through the
40
+ pool when we repopulate the map on every fd_gossip_stakes_update
41
+ iteration. */
42
+ #define POOL_NAME stake_pool
43
+ #define POOL_T stake_t
44
+ #define POOL_IDX_T ulong
45
+ #define POOL_NEXT pool.next
46
+ #include "../../util/tmpl/fd_pool.c"
30
47
31
48
#define MAP_NAME stake_map
32
- #define MAP_T stake_weight_entry_t
49
+ #define MAP_KEY pubkey
50
+ #define MAP_ELE_T stake_t
33
51
#define MAP_KEY_T fd_pubkey_t
34
- #define MAP_HASH_T ulong
35
- #define MAP_KEY_NULL pubkey_null
36
- #define MAP_KEY_EQUAL (k0 ,k1 ) (!(memcmp((k0).key,(k1).key,sizeof(fd_pubkey_t))))
37
- #define MAP_KEY_INVAL (k ) (MAP_KEY_EQUAL((k),MAP_KEY_NULL))
38
- #define MAP_KEY_HASH (key ) ((key).ui[3])
39
- #define MAP_KEY_MOVE (k0 ,k1 ) (fd_memcpy((k0).key,(k1).key,sizeof(fd_pubkey_t) ))
40
- #define MAP_KEY_EQUAL_IS_SLOW 1
41
- #define MAP_LG_SLOT_CNT CRDS_MAX_CONTACT_INFO_LG
42
-
43
- #include "../../util/tmpl/fd_map.c"
52
+ #define MAP_PREV map.prev
53
+ #define MAP_NEXT map.next
54
+ #define MAP_KEY_EQ (k0 ,k1 ) fd_pubkey_eq( k0, k1 )
55
+ #define MAP_KEY_HASH (key ,seed ) (seed^fd_ulong_load_8( (key)->uc ))
56
+ #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
57
+ #include "../../util/tmpl/fd_map_chain.c"
44
58
45
59
#include "fd_push_set_private.c"
46
60
@@ -62,7 +76,11 @@ struct fd_gossip_private {
62
76
63
77
fd_rng_t * rng ;
64
78
65
- stake_weight_entry_t * stake_weights ;
79
+ struct {
80
+ ulong count ;
81
+ stake_t * pool ;
82
+ stake_map_t * map ;
83
+ } stake ;
66
84
67
85
struct {
68
86
long next_pull_request ;
@@ -104,12 +122,13 @@ fd_gossip_footprint( ulong max_values,
104
122
ulong entrypoints_len ) {
105
123
ulong l ;
106
124
l = FD_LAYOUT_INIT ;
107
- l = FD_LAYOUT_APPEND ( l , alignof(fd_gossip_t ), sizeof (fd_gossip_t ) );
108
- l = FD_LAYOUT_APPEND ( l , fd_crds_align (), fd_crds_footprint ( max_values , max_values ) );
109
- l = FD_LAYOUT_APPEND ( l , fd_active_set_align (), fd_active_set_footprint () );
110
- l = FD_LAYOUT_APPEND ( l , fd_ping_tracker_align (), fd_ping_tracker_footprint ( entrypoints_len ) );
111
- l = FD_LAYOUT_APPEND ( l , stake_map_align (), stake_map_footprint () );
112
- l = FD_LAYOUT_APPEND ( l , push_set_align (), push_set_footprint ( FD_ACTIVE_SET_MAX_PEERS ) );
125
+ l = FD_LAYOUT_APPEND ( l , alignof(fd_gossip_t ), sizeof (fd_gossip_t ) );
126
+ l = FD_LAYOUT_APPEND ( l , fd_crds_align (), fd_crds_footprint ( max_values , max_values ) );
127
+ l = FD_LAYOUT_APPEND ( l , fd_active_set_align (), fd_active_set_footprint () );
128
+ l = FD_LAYOUT_APPEND ( l , fd_ping_tracker_align (), fd_ping_tracker_footprint ( entrypoints_len ) );
129
+ l = FD_LAYOUT_APPEND ( l , stake_pool_align (), stake_pool_footprint ( CRDS_MAX_CONTACT_INFO ) );
130
+ l = FD_LAYOUT_APPEND ( l , stake_map_align (), stake_map_footprint ( stake_map_chain_cnt_est ( CRDS_MAX_CONTACT_INFO ) ) );
131
+ l = FD_LAYOUT_APPEND ( l , push_set_align (), push_set_footprint ( FD_ACTIVE_SET_MAX_PEERS ) );
113
132
l = FD_LAYOUT_FINI ( l , fd_gossip_align () );
114
133
return l ;
115
134
}
@@ -167,13 +186,15 @@ fd_gossip_new( void * shmem,
167
186
FD_LOG_WARNING (( "max_values must be a power of 2" ));
168
187
return NULL ;
169
188
}
189
+ ulong stake_map_chain_cnt = stake_map_chain_cnt_est ( max_values );
170
190
171
191
FD_SCRATCH_ALLOC_INIT ( l , shmem );
172
192
fd_gossip_t * gossip = FD_SCRATCH_ALLOC_APPEND ( l , alignof(fd_gossip_t ), sizeof (fd_gossip_t ) );
173
- void * crds = FD_SCRATCH_ALLOC_APPEND ( l , fd_crds_align (), fd_crds_footprint ( max_values , max_values ) );
193
+ void * crds = FD_SCRATCH_ALLOC_APPEND ( l , fd_crds_align (), fd_crds_footprint ( max_values , max_values ) );
174
194
void * active_set = FD_SCRATCH_ALLOC_APPEND ( l , fd_active_set_align (), fd_active_set_footprint () );
175
195
void * ping_tracker = FD_SCRATCH_ALLOC_APPEND ( l , fd_ping_tracker_align (), fd_ping_tracker_footprint ( entrypoints_cnt ) );
176
- void * stake_weights = FD_SCRATCH_ALLOC_APPEND ( l , stake_map_align (), stake_map_footprint () );
196
+ void * stake_pool = FD_SCRATCH_ALLOC_APPEND ( l , stake_pool_align (), stake_pool_footprint ( CRDS_MAX_CONTACT_INFO ) );
197
+ void * stake_weights = FD_SCRATCH_ALLOC_APPEND ( l , stake_map_align (), stake_map_footprint ( stake_map_chain_cnt ) );
177
198
void * active_ps = FD_SCRATCH_ALLOC_APPEND ( l , push_set_align (), push_set_footprint ( FD_ACTIVE_SET_MAX_PEERS ) );
178
199
179
200
gossip -> gossip_net_out = gossip_net_out ;
@@ -190,8 +211,12 @@ fd_gossip_new( void * shmem,
190
211
gossip -> ping_tracker = fd_ping_tracker_join ( fd_ping_tracker_new ( ping_tracker , rng , gossip -> entrypoints_cnt , gossip -> entrypoints , ping_tracker_change , gossip ) );
191
212
FD_TEST ( gossip -> ping_tracker );
192
213
193
- gossip -> stake_weights = stake_map_join ( stake_map_new ( stake_weights ) );
194
- FD_TEST ( gossip -> stake_weights );
214
+ gossip -> stake .count = 0UL ;
215
+ gossip -> stake .pool = stake_pool_join ( stake_pool_new ( stake_pool , CRDS_MAX_CONTACT_INFO ) );
216
+ FD_TEST ( gossip -> stake .pool );
217
+
218
+ gossip -> stake .map = stake_map_join ( stake_map_new ( stake_weights , stake_map_chain_cnt , fd_rng_ulong ( rng ) ) );
219
+ FD_TEST ( gossip -> stake .map );
195
220
196
221
gossip -> active_pset = push_set_join ( push_set_new ( active_ps , FD_ACTIVE_SET_MAX_PEERS ) );
197
222
FD_TEST ( gossip -> active_pset );
@@ -380,9 +405,8 @@ fd_gossip_set_my_contact_info( fd_gossip_t * gossip,
380
405
ulong
381
406
get_stake ( fd_gossip_t const * gossip ,
382
407
uchar const * pubkey ) {
383
- stake_weight_entry_t const * entry = stake_map_query_const ( gossip -> stake_weights , * (fd_pubkey_t const * )pubkey , NULL );
408
+ stake_t const * entry = stake_map_ele_query_const ( gossip -> stake . map , (fd_pubkey_t const * )pubkey , NULL , gossip -> stake . pool );
384
409
if ( FD_UNLIKELY ( !entry ) ) return 0UL ;
385
-
386
410
return entry -> stake ;
387
411
}
388
412
@@ -394,17 +418,22 @@ fd_gossip_stakes_update( fd_gossip_t * gossip,
394
418
FD_LOG_ERR (( "stake_weights_cnt %lu exceeds maximum of %d" , stake_weights_cnt , CRDS_MAX_CONTACT_INFO ));
395
419
}
396
420
397
- stake_map_clear ( gossip -> stake_weights );
421
+ /* Clear the map, this requires us to iterate through all elements and
422
+ individually call map remove. */
423
+ for ( ulong i = 0UL ; i < gossip -> stake .count ; i ++ ) {
424
+ stake_map_idx_remove_fast ( gossip -> stake .map , i , gossip -> stake .pool );
425
+ }
398
426
399
427
for ( ulong i = 0UL ; i < stake_weights_cnt ; i ++ ) {
400
- stake_weight_entry_t * entry = stake_map_insert ( gossip -> stake_weights , stake_weights [i ].key );
401
- if ( FD_UNLIKELY ( !entry ) ) {
402
- FD_LOG_ERR (( "Failed to insert stake weight" ));
403
- }
428
+ stake_t * entry = stake_pool_ele ( gossip -> stake .pool , i );
429
+ fd_memcpy ( entry -> pubkey .uc , stake_weights [i ].key .uc , 32UL );
404
430
entry -> stake = stake_weights [i ].stake ;
431
+
432
+ stake_map_idx_insert ( gossip -> stake .map , i , gossip -> stake .pool );
405
433
}
406
434
/* Update the identity stake */
407
435
gossip -> identity_stake = get_stake ( gossip , gossip -> identity_pubkey );
436
+ gossip -> stake .count = stake_weights_cnt ;
408
437
}
409
438
410
439
static void
0 commit comments