Line data Source code
1 : #include "../fd_config.h"
2 : #include "../fd_action.h"
3 :
4 : #include <unistd.h>
5 :
6 : struct mem_obj_entry {
7 : ulong footprint;
8 : char wksp[ 13 ];
9 : char obj[ 13 ];
10 : };
11 : typedef struct mem_obj_entry mem_obj_entry_t;
12 :
13 : #define SORT_NAME sort_obj_by_footprint
14 0 : #define SORT_KEY_T mem_obj_entry_t
15 0 : #define SORT_BEFORE(a,b) ((a).footprint>(b).footprint)
16 : #include "../../../util/tmpl/fd_sort.c"
17 :
18 : extern action_t * ACTIONS[];
19 :
20 : static void
21 : mem_cmd_args( int * pargc,
22 : char *** pargv,
23 0 : args_t * args ) {
24 0 : char const * topo_name = fd_env_strip_cmdline_cstr( pargc, pargv, "--topo", NULL, "" );
25 0 : args->mem.sort = fd_env_strip_cmdline_contains( pargc, pargv, "--sort" );
26 :
27 0 : ulong topo_name_len = strlen( topo_name );
28 0 : if( FD_UNLIKELY( topo_name_len > sizeof(args->mem.topo)-1 ) ) FD_LOG_ERR(( "Unknown --topo %s", topo_name ));
29 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( args->mem.topo ), topo_name, topo_name_len ) );
30 0 : }
31 :
32 : static void
33 : reconstruct_topo( config_t * config,
34 0 : char const * topo_name ) {
35 0 : if( !topo_name[0] ) return; /* keep default action topo */
36 :
37 0 : action_t const * selected = NULL;
38 0 : for( action_t ** a=ACTIONS; *a; a++ ) {
39 0 : action_t const * action = *a;
40 0 : if( 0==strcmp( action->name, topo_name ) ) {
41 0 : selected = action;
42 0 : break;
43 0 : }
44 0 : }
45 :
46 0 : if( !selected ) FD_LOG_ERR(( "Unknown --topo %s", topo_name ));
47 0 : if( !selected->topo ) FD_LOG_ERR(( "Cannot recover topology for --topo %s", topo_name ));
48 :
49 0 : selected->topo( config );
50 0 : }
51 :
52 : void
53 : mem_cmd_fn( args_t * args,
54 0 : config_t * config ) {
55 0 : reconstruct_topo( config, args->mem.topo );
56 :
57 0 : if( FD_UNLIKELY( args->mem.sort ) ) {
58 0 : fd_topo_t * topo = &config->topo;
59 :
60 : /* Max entries: objects + per-wksp loose + per-wksp overhead + extra pages */
61 0 : mem_obj_entry_t entries[ FD_TOPO_MAX_OBJS + 2UL*FD_TOPO_MAX_WKSPS + 2UL ];
62 0 : ulong cnt = 0UL;
63 :
64 : /* Real topology objects */
65 0 : for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
66 0 : fd_topo_obj_t * obj = &topo->objs[ i ];
67 0 : entries[ cnt ].footprint = obj->footprint;
68 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].wksp ), topo->workspaces[ obj->wksp_id ].name, sizeof(entries[ cnt ].wksp)-1 ) );
69 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].obj ), obj->name, sizeof(entries[ cnt ].obj)-1 ) );
70 0 : cnt++;
71 0 : }
72 :
73 : /* Per-workspace loose memory and page rounding overhead */
74 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
75 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ i ];
76 0 : ulong loose = wksp->total_footprint - wksp->known_footprint;
77 0 : if( loose ) {
78 0 : entries[ cnt ].footprint = loose;
79 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].wksp ), wksp->name, sizeof(entries[ cnt ].wksp)-1 ) );
80 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].obj ), "loose", 5 ) );
81 0 : cnt++;
82 0 : }
83 0 : ulong pages_sz = wksp->page_cnt * wksp->page_sz;
84 0 : ulong overhead = pages_sz - wksp->total_footprint;
85 0 : if( overhead ) {
86 0 : entries[ cnt ].footprint = overhead;
87 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].wksp ), wksp->name, sizeof(entries[ cnt ].wksp)-1 ) );
88 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].obj ), "padding", 7 ) );
89 0 : cnt++;
90 0 : }
91 0 : }
92 :
93 : /* Tile stacks: each tile maps (FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2
94 : huge pages for its stack (see fd_topo_tile_extra_huge_pages). */
95 0 : ulong stack_huge_pages = topo->tile_cnt * ((FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL);
96 0 : if( stack_huge_pages ) {
97 0 : entries[ cnt ].footprint = stack_huge_pages * FD_SHMEM_HUGE_PAGE_SZ;
98 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].wksp ), "", 0 ) );
99 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].obj ), "tile_stacks", 11 ) );
100 0 : cnt++;
101 0 : }
102 :
103 : /* Extra normal pages (private keys, XSK rings, log locks, etc.) */
104 0 : ulong extra_normal = fd_topo_normal_page_cnt( topo );
105 0 : if( extra_normal ) {
106 0 : entries[ cnt ].footprint = extra_normal * FD_SHMEM_NORMAL_PAGE_SZ;
107 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].wksp ), "", 0 ) );
108 0 : fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( entries[ cnt ].obj ), "normal_pages", 12 ) );
109 0 : cnt++;
110 0 : }
111 :
112 0 : sort_obj_by_footprint_inplace( entries, cnt );
113 :
114 0 : ulong total = 0UL;
115 0 : for( ulong i=0UL; i<cnt; i++ ) total += entries[ i ].footprint;
116 :
117 0 : FD_LOG_STDOUT(( "%7s %6s %15s %12s %12s\n", "SIZE", "PCT", "BYTES", "WORKSPACE", "OBJECT" ));
118 0 : FD_LOG_STDOUT(( "------- ------ --------------- ------------ ------------\n" ));
119 0 : for( ulong i=0UL; i<cnt; i++ ) {
120 0 : ulong sz = entries[ i ].footprint;
121 0 : char sz_str[ 24 ];
122 0 : if( FD_LIKELY( sz >= (1UL<<30) ) ) FD_TEST( fd_cstr_printf_check( sz_str, 24, NULL, "%lu GiB", sz / (1UL<<30) ) );
123 0 : else if( FD_LIKELY( sz >= (1UL<<20) ) ) FD_TEST( fd_cstr_printf_check( sz_str, 24, NULL, "%lu MiB", sz / (1UL<<20) ) );
124 0 : else if( FD_LIKELY( sz >= (1UL<<10) ) ) FD_TEST( fd_cstr_printf_check( sz_str, 24, NULL, "%lu KiB", sz / (1UL<<10) ) );
125 0 : else FD_TEST( fd_cstr_printf_check( sz_str, 24, NULL, "%lu B", sz ) );
126 0 : double pct = total ? 100.0 * (double)sz / (double)total : 0.0;
127 0 : FD_LOG_STDOUT(( "%7s %5.1f%% %15lu %12s %12s\n", sz_str, pct, sz, entries[ i ].wksp, entries[ i ].obj ));
128 0 : }
129 :
130 0 : char total_str[ 24 ];
131 0 : if( FD_LIKELY( total >= (1UL<<30) ) ) FD_TEST( fd_cstr_printf_check( total_str, 24, NULL, "%lu GiB", total / (1UL<<30) ) );
132 0 : else if( FD_LIKELY( total >= (1UL<<20) ) ) FD_TEST( fd_cstr_printf_check( total_str, 24, NULL, "%lu MiB", total / (1UL<<20) ) );
133 0 : else if( FD_LIKELY( total >= (1UL<<10) ) ) FD_TEST( fd_cstr_printf_check( total_str, 24, NULL, "%lu KiB", total / (1UL<<10) ) );
134 0 : else FD_TEST( fd_cstr_printf_check( total_str, 24, NULL, "%lu B", total ) );
135 0 : FD_LOG_STDOUT(( "------- ------ --------------- ------------ ------------\n" ));
136 0 : FD_LOG_STDOUT(( "%7s %5.1f%% %15lu %12s\n", total_str, 100.0, total, "TOTAL" ));
137 0 : return;
138 0 : }
139 :
140 0 : fd_topo_print_log( 1, &config->topo );
141 0 : }
142 :
143 : action_t fd_action_mem = {
144 : .name = "mem",
145 : .args = mem_cmd_args,
146 : .fn = mem_cmd_fn,
147 : .require_config = 1,
148 : .perm = NULL,
149 : .description = "Print workspace memory and tile topology information",
150 : };
|