Skip to content

Commit ea39afe

Browse files
riptlripatel-fd
authored andcommitted
vm: add pointer chasing benchmark
1 parent 07a3534 commit ea39afe

File tree

2 files changed

+162
-1
lines changed

2 files changed

+162
-1
lines changed

src/flamenco/vm/Local.mk

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
ifdef FD_HAS_INT128
21
ifdef FD_HAS_HOSTED
2+
ifdef FD_HAS_INT128
33
ifdef FD_HAS_SECP256K1
44

55
$(call add-hdrs,fd_vm_base.h fd_vm.h fd_vm_private.h) # FIXME: PRIVATE TEMPORARILY HERE DUE TO SOME MESSINESS IN FD_VM_SYSCALL.H
@@ -22,4 +22,7 @@ $(call run-unit-test,test_vm_base)
2222
$(call run-unit-test,test_vm_interp)
2323
endif
2424
endif
25+
26+
$(call make-unit-test,test_pointer_chase,test_pointer_chase,fd_util)
27+
$(call run-unit-test,test_pointer_chase)
2528
endif

src/flamenco/vm/test_pointer_chase.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#include "../../util/fd_util.h"
2+
#include <stdio.h>
3+
4+
/* RNG patterns */
5+
6+
typedef void
7+
(* pattern_fn_t)( ulong * ptr,
8+
ulong sz,
9+
fd_rng_t * rng );
10+
11+
static void pattern_seq( ulong * ptr, ulong n, fd_rng_t * rng ) {
12+
(void)rng;
13+
for( ulong i=0UL; i<n; i++ ) {
14+
ptr[i] = (ulong)ptr + 8*i;
15+
}
16+
}
17+
18+
static void pattern_random( ulong * ptr, ulong n, fd_rng_t * rng ) {
19+
/* Create a random permutation */
20+
for( ulong i=0UL; i<n; i++ ) {
21+
ptr[i] = (ulong)ptr + 8*i;
22+
}
23+
/* Fisher-Yates shuffle */
24+
for( ulong i=0UL; i<=n-2; i++ ) {
25+
ulong j = i+fd_rng_ulong_roll( rng, n-i );
26+
fd_swap( ptr[i], ptr[j] );
27+
}
28+
}
29+
30+
static const struct {
31+
char const * name;
32+
char const * help;
33+
pattern_fn_t fn;
34+
} patterns[] = {
35+
{
36+
.name = "seq",
37+
.help = "sequential scan",
38+
.fn = pattern_seq
39+
},
40+
{
41+
.name = "random",
42+
.help = "random permutation",
43+
.fn = pattern_random
44+
},
45+
{0}
46+
};
47+
48+
/* Pointer chasing test */
49+
50+
51+
static ulong
52+
ptr_chase_block( ulong x ) {
53+
#define ITER_BLOCK 512
54+
#pragma GCC unroll 512
55+
for( ulong i=0UL; i<ITER_BLOCK; i++ ) {
56+
x = *(ulong *)x;
57+
}
58+
return x;
59+
}
60+
61+
static ulong
62+
ptr_chase( ulong * ptr, ulong iter ) {
63+
ulong x = (ulong)ptr;
64+
while( iter>=ITER_BLOCK ) {
65+
x = ptr_chase_block( x );
66+
iter -= ITER_BLOCK;
67+
}
68+
while( iter-- ) x = *(ulong *)x;
69+
return x;
70+
}
71+
72+
/* Command-line handling */
73+
74+
int
75+
main( int argc,
76+
char ** argv ) {
77+
int const help_requested = fd_env_strip_cmdline_contains( &argc, &argv, "--help" );
78+
if( FD_UNLIKELY( help_requested ) ) {
79+
fputs(
80+
"\nUsage: test_pointer_chase [workspace] [--size 10e6] [--pattern PATTERN]\n"
81+
"\n"
82+
" anonymous workspace:\n"
83+
" --page-sz normal/huge/gigantic\n"
84+
" --near-cpu 0\n"
85+
"\n"
86+
" existing workspace:\n"
87+
" --wksp NAME\n"
88+
"\n"
89+
" Supported patterns:\n"
90+
"\n",
91+
stderr );
92+
for( ulong i=0UL; patterns[i].name; i++ ) {
93+
fprintf( stderr, " %-10s %s\n", patterns[i].name, patterns[i].help );
94+
}
95+
fputs( "\n", stderr );
96+
return 0;
97+
}
98+
99+
fd_boot( &argc, &argv );
100+
char const * name = fd_env_strip_cmdline_cstr ( &argc, &argv, "--wksp", NULL, NULL );
101+
char const * _page_sz = fd_env_strip_cmdline_cstr ( &argc, &argv, "--page-sz", NULL, "normal" );
102+
ulong near_cpu = fd_env_strip_cmdline_ulong( &argc, &argv, "--near-cpu", NULL, fd_log_cpu_id() );
103+
float size_f = fd_env_strip_cmdline_float( &argc, &argv, "--size", NULL, 10e6 );
104+
char const * pattern = fd_env_strip_cmdline_cstr ( &argc, &argv, "--pattern", NULL, "random" );
105+
float iter_f = fd_env_strip_cmdline_float( &argc, &argv, "--iter", NULL, 1e7 );
106+
107+
ulong size = (ulong)size_f;
108+
if( FD_UNLIKELY( !size || size > (1UL<<46) ) ) FD_LOG_ERR(( "Invalid --size" ));
109+
110+
ulong page_sz = fd_cstr_to_shmem_page_sz( _page_sz );
111+
if( FD_UNLIKELY( !page_sz ) ) FD_LOG_ERR(( "Invalid --page-sz %s", _page_sz ));
112+
113+
fd_rng_t _rng[1];
114+
fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, 0U, 0UL ) );
115+
116+
fd_wksp_t * wksp;
117+
if( name ) {
118+
FD_LOG_NOTICE(( "Attaching to --wksp %s", name ));
119+
wksp = fd_wksp_attach( name );
120+
} else {
121+
ulong page_cnt = fd_ulong_align_up( size + 16384UL, page_sz ) / page_sz;
122+
FD_LOG_NOTICE(( "--wksp not specified, using an anonymous local workspace, --page-sz %s, --page-cnt %lu, --near-cpu %lu",
123+
_page_sz, page_cnt, near_cpu ));
124+
wksp = fd_wksp_new_anonymous( fd_cstr_to_shmem_page_sz( _page_sz ), page_cnt, near_cpu, "wksp", 2UL );
125+
if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "fd_wksp_new_anonymous failed" ));
126+
}
127+
128+
ulong line_cnt = fd_ulong_align_up( size, sizeof(ulong) )>>3;
129+
ulong * scratch = fd_wksp_alloc_laddr( wksp, alignof(ulong), line_cnt*sizeof(ulong), 1UL );
130+
if( FD_UNLIKELY( !scratch ) ) FD_LOG_ERR(( "Unable to allocate scratch" ));
131+
132+
pattern_fn_t pat_fn = NULL;
133+
for( ulong i=0UL; patterns[i].name; i++ ) {
134+
if( 0==strcmp( patterns[i].name, pattern ) ) {
135+
pat_fn = patterns[i].fn;
136+
break;
137+
}
138+
}
139+
if( FD_UNLIKELY( !pat_fn ) ) FD_LOG_ERR(( "Unsupported --pattern %s", pattern ));
140+
141+
long dt = -fd_log_wallclock();
142+
FD_LOG_NOTICE(( "Params: --pattern \"%s\" --size %g --iter %g", pattern, (double)line_cnt*8, (double)iter_f ));
143+
pat_fn( scratch, line_cnt, rng );
144+
dt += fd_log_wallclock();
145+
FD_LOG_NOTICE(( "PATTERN elapsed=%.2es", (double)dt/1e9 ));
146+
147+
dt = -fd_log_wallclock();
148+
ulong res = ptr_chase( scratch, (ulong)iter_f );
149+
FD_COMPILER_UNPREDICTABLE( res );
150+
dt += fd_log_wallclock();
151+
FD_LOG_NOTICE(( "BENCH elapsed=%.2es iter=%.1e period=%.2fns", (double)dt/1e9, (double)iter_f, (double)dt/(double)iter_f ));
152+
153+
if( name ) fd_wksp_detach( wksp );
154+
else fd_wksp_delete_anonymous( wksp );
155+
fd_rng_delete( fd_rng_leave( rng ) );
156+
fd_halt();
157+
return 0;
158+
}

0 commit comments

Comments
 (0)