Line data Source code
1 : #include "fd_memusage.h"
2 : #include "../wksp/fd_wksp_private.h"
3 : #include "../shmem/fd_shmem_private.h"
4 : #include <stdio.h>
5 : #include <stdlib.h>
6 :
7 : static const char *
8 0 : print_smart_sz( char * buf, uint buf_sz, ulong sz ) {
9 0 : if( sz < 1024UL/2) {
10 0 : snprintf( buf, buf_sz, "%luB", sz);
11 0 : } else if( sz < 1024UL*1024/2) {
12 0 : snprintf( buf, buf_sz, "%.2fKB", ((double)sz)/1024.0 );
13 0 : } else if( sz < 1024UL*1024*1024/2) {
14 0 : snprintf( buf, buf_sz, "%.2fMB", ((double)sz)/(1024.0*1024.0) );
15 0 : } else {
16 0 : snprintf( buf, buf_sz, "%.2fGB", ((double)sz)/(1024.0*1024.0*1024.0) );
17 0 : }
18 0 : return buf;
19 0 : }
20 :
21 : static int
22 0 : fd_wksp_private_pinfo_cmp( const void * a, const void * b ) {
23 0 : fd_wksp_private_pinfo_t * ptr_a = *(fd_wksp_private_pinfo_t **)a;
24 0 : ulong sz_a = ptr_a->gaddr_hi - ptr_a->gaddr_lo;
25 0 : fd_wksp_private_pinfo_t * ptr_b = *(fd_wksp_private_pinfo_t **)b;
26 0 : ulong sz_b = ptr_b->gaddr_hi - ptr_b->gaddr_lo;
27 0 : return (sz_a > sz_b) ? -1 : (( sz_a < sz_b ) ? 1 : 0);
28 0 : }
29 :
30 0 : #define PART_LIST_MAX_MAX (1U<<20)
31 : static fd_wksp_private_pinfo_t * part_list[PART_LIST_MAX_MAX];
32 :
33 : void
34 0 : fd_memusage_printout_wksp( FILE * fp, fd_wksp_t * wksp ) {
35 0 : char buf[128];
36 0 : char buf2[128];
37 :
38 0 : fprintf( fp, " wksp: part_max=%lu, data_max=%s\n",
39 0 : wksp->part_max, print_smart_sz(buf, sizeof(buf), wksp->data_max) );
40 :
41 : // Print out the partition info
42 0 : fd_wksp_private_pinfo_t * part_info = (fd_wksp_private_pinfo_t *)((const unsigned char *)wksp + fd_wksp_private_pinfo_off());
43 0 : ulong list_cnt = 0UL;
44 0 : for( ulong part_idx=0UL; part_idx<wksp->part_max && part_idx<PART_LIST_MAX_MAX; part_idx++ ) {
45 0 : if( part_info[part_idx].gaddr_hi == 0UL || part_info[part_idx].tag == 0 ) continue;
46 0 : part_list[list_cnt++] = &part_info[part_idx];
47 0 : }
48 :
49 : // Sort the list by size
50 0 : qsort( part_list, list_cnt, sizeof(fd_wksp_private_pinfo_t *), fd_wksp_private_pinfo_cmp );
51 :
52 : // Print out the partition info
53 0 : ulong prev_sz = 0UL;
54 0 : ulong prev_tag = 0UL;
55 0 : ulong group_cnt = 0UL;
56 0 : ulong tot_sz = 0UL;
57 0 : for( ulong idx=0UL; idx<list_cnt; idx++ ) {
58 0 : fd_wksp_private_pinfo_t * ptr = part_list[idx];
59 0 : ulong sz = ptr->gaddr_hi - ptr->gaddr_lo;
60 0 : tot_sz += sz;
61 : // Group by size and tag
62 0 : if( group_cnt && !((prev_sz == sz) && (prev_tag == ptr->tag)) ) {
63 0 : fprintf( fp, " parts: sz=%s, tag=%lu, cnt=%lu, tot_sz=%s\n",
64 0 : print_smart_sz(buf, sizeof(buf), prev_sz), prev_tag, group_cnt,
65 0 : print_smart_sz(buf2, sizeof(buf2), group_cnt*prev_sz) );
66 0 : group_cnt = 0UL;
67 0 : }
68 0 : group_cnt++;
69 0 : prev_sz = sz;
70 0 : prev_tag = ptr->tag;
71 0 : }
72 0 : if( group_cnt > 0UL ) {
73 0 : fprintf( fp, " parts: sz=%s, tag=%lu, cnt=%lu, tot_sz=%s\n",
74 0 : print_smart_sz(buf, sizeof(buf), prev_sz), prev_tag, group_cnt,
75 0 : print_smart_sz(buf2, sizeof(buf2), group_cnt*prev_sz) );
76 0 : }
77 0 : fprintf( fp, " parts: tot_tot_sz=%s, wksp usage=%.3f%%\n",
78 0 : print_smart_sz(buf, sizeof(buf), tot_sz),
79 0 : ((double)tot_sz)/((double)wksp->data_max)*100.0 );
80 :
81 0 : return;
82 0 : }
83 :
84 0 : static int fd_shmem_join_info_cmp( const void * a, const void * b ) {
85 0 : fd_shmem_join_info_t * ptr_a = *(fd_shmem_join_info_t **)a;
86 0 : ulong sz_a = ptr_a->page_sz*ptr_a->page_cnt;
87 0 : fd_shmem_join_info_t * ptr_b = *(fd_shmem_join_info_t **)b;
88 0 : ulong sz_b = ptr_b->page_sz*ptr_b->page_cnt;
89 0 : return (sz_a > sz_b) ? -1 : (( sz_a < sz_b ) ? 1 : 0);
90 0 : }
91 :
92 0 : void fd_memusage_printout( const char * filename ) {
93 0 : char buf[128];
94 :
95 0 : FILE * fp = ( (filename == NULL) ? stderr : fopen( filename, "w" ) );
96 0 : if( !fp ) {
97 0 : FD_LOG_WARNING(( "failed to open file %s", filename ));
98 0 : return;
99 0 : }
100 :
101 : // Loop over all the shmems
102 0 : #define SHMEM_PTRS_MAX (1U<<8)
103 0 : fd_shmem_join_info_t const * ptrs[SHMEM_PTRS_MAX];
104 0 : ulong ptrs_cnt = 0UL;
105 0 : for( fd_shmem_join_info_t const * iter = fd_shmem_iter_begin();
106 0 : ptrs_cnt<SHMEM_PTRS_MAX && !fd_shmem_iter_done(iter);
107 0 : iter = fd_shmem_iter_next(iter) ) {
108 0 : ptrs[ptrs_cnt++] = iter;
109 0 : }
110 :
111 : // Sort the shmemptrs by size
112 0 : qsort( ptrs, ptrs_cnt, sizeof(fd_shmem_join_info_t *), fd_shmem_join_info_cmp );
113 :
114 : // Print out the shmems
115 0 : ulong tot_sz = 0UL;
116 0 : for( ulong ptr_idx=0UL; ptr_idx<ptrs_cnt; ptr_idx++ ) {
117 0 : fd_shmem_join_info_t const * ptr = ptrs[ptr_idx];
118 0 : ulong sz = ptr->page_sz*ptr->page_cnt;
119 0 : tot_sz += sz;
120 0 : const char * name = (ptr->name[0] == '\0') ? "unnamed" : ptr->name;
121 0 : fprintf( fp, "shmem: %s %p...%p %s\n", name,
122 0 : (void *)ptr->shmem, (void *)(((const uchar *)ptr->shmem)+sz),
123 0 : print_smart_sz(buf, sizeof(buf), sz) );
124 :
125 : // Check if the shmem is a wksp
126 0 : if( strlen(name) > 5 && strcmp(name + strlen(name) - 5, ".wksp") == 0 ) {
127 0 : fd_wksp_t * wksp = (fd_wksp_t *)ptr->join;
128 0 : if( FD_UNLIKELY( wksp == NULL || sz < sizeof(fd_wksp_t) || wksp->magic!=FD_WKSP_MAGIC ) ) continue;
129 0 : fd_memusage_printout_wksp( fp, wksp );
130 0 : }
131 0 : }
132 :
133 0 : fprintf( fp, "all shmem: tot_sz=%s\n", print_smart_sz(buf, sizeof(buf), tot_sz) );
134 :
135 0 : fflush( fp );
136 0 : if( fp != stderr ) { fclose( fp ); }
137 :
138 0 : return;
139 0 : }
|