* See prof_sample_new_event_wait() comment for why the body of this function * is conditionally compiled. */
| 1013 | * is conditionally compiled. |
| 1014 | */ |
| 1015 | static void |
| 1016 | prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx) { |
| 1017 | #ifdef JEMALLOC_PROF |
| 1018 | /* |
| 1019 | * Scaling is equivalent AdjustSamples() in jeprof, but the result may |
| 1020 | * differ slightly from what jeprof reports, because here we scale the |
| 1021 | * summary values, whereas jeprof scales each context individually and |
| 1022 | * reports the sums of the scaled values. |
| 1023 | */ |
| 1024 | if (cnt_all->curbytes != 0) { |
| 1025 | double sample_period = (double)((uint64_t)1 << lg_prof_sample); |
| 1026 | double ratio = (((double)cnt_all->curbytes) / |
| 1027 | (double)cnt_all->curobjs) / sample_period; |
| 1028 | double scale_factor = 1.0 / (1.0 - exp(-ratio)); |
| 1029 | uint64_t curbytes = (uint64_t)round(((double)cnt_all->curbytes) |
| 1030 | * scale_factor); |
| 1031 | uint64_t curobjs = (uint64_t)round(((double)cnt_all->curobjs) * |
| 1032 | scale_factor); |
| 1033 | |
| 1034 | malloc_printf("<jemalloc>: Leak approximation summary: ~%"FMTu64 |
| 1035 | " byte%s, ~%"FMTu64" object%s, >= %zu context%s\n", |
| 1036 | curbytes, (curbytes != 1) ? "s" : "", curobjs, (curobjs != |
| 1037 | 1) ? "s" : "", leak_ngctx, (leak_ngctx != 1) ? "s" : ""); |
| 1038 | malloc_printf( |
| 1039 | "<jemalloc>: Run jeprof on dump output for leak detail\n"); |
| 1040 | if (opt_prof_leak_error) { |
| 1041 | malloc_printf( |
| 1042 | "<jemalloc>: Exiting with error code because memory" |
| 1043 | " leaks were detected\n"); |
| 1044 | /* |
| 1045 | * Use _exit() with underscore to avoid calling atexit() |
| 1046 | * and entering endless cycle. |
| 1047 | */ |
| 1048 | _exit(1); |
| 1049 | } |
| 1050 | } |
| 1051 | #endif |
| 1052 | } |
| 1053 | |
| 1054 | static prof_gctx_t * |
| 1055 | prof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) { |
no test coverage detected