/* All this code should be usable from within C apps. */#ifdef __cplusplusextern"C"{#endif/* Start profiling and write profile info into fname, discarding any * existing profiling data in that file. * * This is equivalent to calling ProfilerStartWithOptions(fname, NULL). */BRPC_DLL_DECLintProfilerStart(constchar*fname);......}
extern"C"{// weak symbol: resolved at runtime by the linker if we are using jemalloc, nullptr otherwiseintBAIDU_WEAKmallctl(constchar*,void*,size_t*,void*,size_t);voidBAIDU_WEAKmalloc_stats_print(void(*write_cb)(void*,constchar*),void*cbopaque,constchar*opts);}
// https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Introspection-Via-mallctl*()#include<stdio.h>#include<stdlib.h>#include<stdint.h>#include<jemalloc/jemalloc.h>voiddo_something(size_ti){// Leak some memory.malloc(i*100);}intmain(intargc,char**argv){size_ti,sz;for(i=0;i<100;i++){do_something(i);// Update the statistics cached by mallctl.uint64_tepoch=1;sz=sizeof(epoch);mallctl("epoch",&epoch,&sz,&epoch,sz);// Get basic allocation statistics. Take care to check for// errors, since --enable-stats must have been specified at// build time for these statistics to be available.size_tsz,allocated,active,metadata,resident,mapped;sz=sizeof(size_t);if(mallctl("stats.allocated",&allocated,&sz,NULL,0)==0&&mallctl("stats.active",&active,&sz,NULL,0)==0&&mallctl("stats.metadata",&metadata,&sz,NULL,0)==0&&mallctl("stats.resident",&resident,&sz,NULL,0)==0&&mallctl("stats.mapped",&mapped,&sz,NULL,0)==0){fprintf(stderr,"Current allocated/active/metadata/resident/mapped: %zu/%zu/%zu/%zu/%zu\n",allocated,active,metadata,resident,mapped);}}return(0);}
The mallctl() function provides a general interface for introspecting the memory allocator, as well as setting modifiable parameters and triggering actions. The period-separated name argument specifies a location in a tree-structured namespace; see the MALLCTL NAMESPACE section for documentation on the tree contents. To read a value, pass a pointer via oldp to adequate space to contain the value, and a pointer to its length via oldlenp; otherwise pass NULL and NULL. Similarly, to write a value, pass a pointer to the value via newp, and its length via newlen; otherwise pass NULL and 0.
staticvoidInitGetInstanceFn(){g_get_instance_fn=(GetInstanceFn)dlsym(RTLD_NEXT,"_ZN15MallocExtension8instanceEv");}MallocExtension*BAIDU_WEAKMallocExtension::instance(){// On fedora 26, this weak function is NOT overriden by the one in tcmalloc// which is dynamically linked.The same issue can't be re-produced in// Ubuntu and the exact cause is unknown yet. Using dlsym to get the// function works around the issue right now. Note that we can't use dlsym// to fully replace the weak-function mechanism since our code are generally// not compiled with -rdynamic which writes symbols to the table that// dlsym reads.pthread_once(&g_get_instance_fn_once,InitGetInstanceFn);if(g_get_instance_fn){returng_get_instance_fn();}returnNULL;}