Line data Source code
1 : #include "fd_funk.h"
2 : #include "fd_funk_base.h"
3 : #include <math.h>
4 :
5 : #define FUNK_TAG 1UL
6 :
7 : __attribute__((noinline)) static void
8 : run_benchmark( fd_funk_t * funk,
9 : fd_rng_t * rng,
10 0 : ulong acc_cnt ) {
11 0 : fd_wksp_t * funk_wksp = fd_funk_wksp( funk );
12 0 : ulong acc_rem=acc_cnt;
13 0 : while( acc_rem-- ) {
14 0 : fd_funk_rec_key_t key;
15 0 : key.ul[ 0 ] = fd_rng_ulong( rng );
16 0 : fd_funk_rec_prepare_t prepare[1];
17 0 : fd_funk_rec_t * rec = fd_funk_rec_prepare( funk, NULL, &key, prepare, NULL );
18 0 : FD_TEST( rec );
19 0 : fd_funk_val_truncate( rec,
20 0 : fd_funk_alloc( funk ),
21 0 : funk_wksp,
22 0 : 0UL,
23 0 : 104,
24 0 : NULL );
25 0 : fd_funk_rec_publish( funk, prepare );
26 0 : }
27 0 : }
28 :
29 : static void
30 0 : stat_chains( fd_funk_t * funk ) {
31 0 : fd_funk_rec_map_t * rec_map = fd_funk_rec_map( funk );
32 0 : fd_funk_rec_map_shmem_private_chain_t * chain_tbl = fd_funk_rec_map_shmem_private_chain( rec_map->map, 0UL );
33 0 : ulong chain_cnt = fd_funk_rec_map_chain_cnt( rec_map );
34 :
35 0 : double sum = 0.0;
36 0 : ulong min = ULONG_MAX;
37 0 : ulong max = 0UL;
38 0 : for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
39 0 : ulong chain_len = fd_funk_rec_map_private_vcnt_cnt( chain_tbl[ chain_idx ].ver_cnt );
40 0 : sum += (double)chain_len;
41 0 : min = fd_ulong_min( min, chain_len );
42 0 : max = fd_ulong_max( max, chain_len );
43 0 : }
44 0 : double mean = sum / (double)chain_cnt;
45 0 : double var = 0.0;
46 0 : for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
47 0 : double diff = (double)fd_funk_rec_map_private_vcnt_cnt( chain_tbl[ chain_idx ].ver_cnt ) - mean;
48 0 : var += diff*diff;
49 0 : }
50 0 : var /= (double)chain_cnt;
51 0 : FD_LOG_NOTICE(( "Chain lengths: min=%lu max=%lu mean=%.2f var=%.2f stddev=%.2f",
52 0 : min, max, (double)mean, (double)var, (double)sqrt(var) ));
53 0 : }
54 :
55 : int
56 : main( int argc,
57 : char ** argv ) {
58 : fd_boot( &argc, &argv );
59 :
60 : char const * name = fd_env_strip_cmdline_cstr ( &argc, &argv, "--wksp", NULL, NULL );
61 : char const * _page_sz = fd_env_strip_cmdline_cstr ( &argc, &argv, "--page-sz", NULL, "gigantic" );
62 : ulong page_cnt = fd_env_strip_cmdline_ulong ( &argc, &argv, "--page-cnt", NULL, 128UL );
63 : ulong near_cpu = fd_env_strip_cmdline_ulong ( &argc, &argv, "--near-cpu", NULL, fd_log_cpu_id() );
64 : double acc_cnt_d = fd_env_strip_cmdline_double( &argc, &argv, "--accounts", NULL, 1e9 );
65 : double rec_max_d = fd_env_strip_cmdline_double( &argc, &argv, "--rec-max", NULL, 1e9 );
66 : uint rng_seed = fd_env_strip_cmdline_uint ( &argc, &argv, "--rng-seed", NULL, 1234UL );
67 : ulong funk_seed = fd_env_strip_cmdline_ulong ( &argc, &argv, "--funk-seed", NULL, 1234UL );
68 : int fast_clean = fd_env_strip_cmdline_int ( &argc, &argv, "--fast-clean", NULL, 1 );
69 :
70 : ulong const txn_max = 16UL;
71 : ulong const acc_cnt = (ulong)acc_cnt_d;
72 : ulong const rec_max = (ulong)rec_max_d;
73 :
74 : fd_rng_t rng_[1];
75 : fd_rng_t * rng = fd_rng_join( fd_rng_new( rng_, rng_seed, 0UL ) );
76 :
77 : ulong page_sz = fd_cstr_to_shmem_page_sz( _page_sz );
78 : if( FD_UNLIKELY( !page_sz ) ) FD_LOG_ERR(( "unsupported --page-sz" ));
79 :
80 : ulong funk_footprint = fd_funk_footprint( txn_max, rec_max );
81 : FD_LOG_NOTICE(( "fd_funk_footprint(txn_max=%lu,rec_max=%g) = %.1f MiB", txn_max, (double)rec_max, (double)funk_footprint/(1024.0*1024.0) ));
82 : ulong chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
83 : FD_LOG_NOTICE(( "fd_funk_rec_map_chain_cnt_est(rec_max=%g) = %g", (double)rec_max, (double)chain_cnt ));
84 : if( FD_UNLIKELY( funk_footprint > (page_cnt*page_sz ) ) ) FD_LOG_ERR(( "funk footprint exceeds memory bounds" ));
85 :
86 : fd_wksp_t * wksp;
87 : if( name ) {
88 : FD_LOG_NOTICE(( "Attaching to --wksp %s", name ));
89 : wksp = fd_wksp_attach( name );
90 : } else {
91 : FD_LOG_NOTICE(( "--wksp not specified, using an anonymous local workspace, --page-sz %s, --page-cnt %lu, --near-cpu %lu",
92 : _page_sz, page_cnt, near_cpu ));
93 : wksp = fd_wksp_new_anonymous( fd_cstr_to_shmem_page_sz( _page_sz ), page_cnt, near_cpu, "wksp", 0UL );
94 : }
95 :
96 : void * funk_mem = fd_wksp_alloc_laddr( wksp, fd_funk_align(), funk_footprint, FUNK_TAG );
97 : if( FD_UNLIKELY( !funk_mem ) ) FD_LOG_ERR(( "failed to allocate funk" ));
98 : fd_funk_t funk_[1];
99 : fd_funk_t * funk = fd_funk_join( funk_, fd_funk_new( funk_mem, FUNK_TAG, funk_seed, 16UL, rec_max ) );
100 : FD_TEST( funk );
101 :
102 : fd_funk_rec_map_t * rec_map = fd_funk_rec_map( funk );
103 : FD_TEST( fd_funk_rec_map_chain_cnt( rec_map ) == chain_cnt );
104 :
105 : FD_LOG_NOTICE(( "Starting insert loop" ));
106 : long dt = -fd_log_wallclock();
107 : run_benchmark( funk, rng, acc_cnt );
108 : dt += fd_log_wallclock();
109 : FD_LOG_NOTICE(( "Inserted %lu accounts in %.2fs (rate=%.2g per_item=%.0fns)",
110 : acc_cnt, (double)dt/1e9,
111 : (double)acc_cnt/( (double)dt/1e9 ),
112 : (double)dt/(double)acc_cnt ));
113 :
114 : stat_chains( funk );
115 :
116 : dt = -fd_log_wallclock();
117 : fd_funk_leave( funk, NULL );
118 : if( fast_clean ) {
119 : fd_funk_delete_fast( funk_mem );
120 : } else {
121 : fd_wksp_free_laddr( fd_funk_delete( funk_mem ) );
122 : }
123 : if( name ) fd_wksp_detach( wksp );
124 : else fd_wksp_delete_anonymous( wksp );
125 : fd_rng_delete( fd_rng_leave( rng ) );
126 : dt += fd_log_wallclock();
127 : FD_LOG_NOTICE(( "Clean up took %.1fs", (double)dt/1e9 ));
128 :
129 : FD_LOG_NOTICE(( "pass" ));
130 : fd_halt();
131 : return 0;
132 : }
|