source: src/Common/Stats/Heap.cc@ 79eaeb7

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 79eaeb7 was 1cb7fab2, checked in by tdelisle <tdelisle@…>, 7 years ago

Added better support for enabling/disabling/compiling-out statistics

  • Property mode set to 100644
File size: 6.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Heap.cc --
8//
9// Author : Thierry Delisle
10// Created On : Thu May 3 16:16:10 2018
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri May 4 17:27:31 2018
13// Update Count : 28
14//
15
16#include <cassert>
17#include <cmath>
18#include <cstddef>
19#include <cstring>
20#include <iomanip>
21#include <iostream>
22
23#if defined( NO_STATISTICS )
24 #define NO_HEAP_STATISTICS
25#endif
26
27namespace Stats {
28 namespace Heap {
29#if defined( NO_HEAP_STATISTICS )
30 void newPass( const char * const ) {}
31
32 void print() {}
33#else
34 extern bool enabled;
35
36 struct StatBlock {
37 const char * name = nullptr; ///< Name of this pass
38 size_t mallocs = 0; ///< Allocations in this pass
39 size_t frees = 0; ///< Frees in this pass
40 size_t n_allocs = 0; ///< Current number of live allocations
41 size_t peak_allocs = 0; ///< Peak number of live allocations this pass
42 };
43
44 StatBlock passes[100] = {{ "Pre-Parse", 0, 0, 0, 0 }};
45 const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
46 size_t passes_cnt = 1;
47
48 void newPass( const char * const name ) {
49 passes[passes_cnt].name = name;
50 passes[passes_cnt].mallocs = 0;
51 passes[passes_cnt].frees = 0;
52 passes[passes_cnt].n_allocs
53 = passes[passes_cnt].peak_allocs
54 = passes[passes_cnt-1].n_allocs;
55 passes_cnt++;
56
57 assertf(passes_cnt < passes_size, "Too many passes for Stats::Heap, increase the size of the array in Heap.cc");
58 }
59
60 void print(size_t value, size_t total) {
61 std::cerr << std::setw(12) << value;
62 std::cerr << "(" << std::setw(3);
63 std::cerr << (value == 0 ? 0 : value * 100 / total);
64 std::cerr << "%) | ";
65 }
66
67 void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees, size_t overall_peak) {
68 std::cerr << std::setw(nc) << stat.name;
69 std::cerr << " | ";
70
71 print(stat.mallocs, total_mallocs);
72 print(stat.frees, total_frees );
73 print(stat.peak_allocs, overall_peak );
74 std::cerr << "\n";
75 }
76
77 void print(char c, size_t nc) {
78 for(size_t i = 0; i < nc; i++) {
79 std::cerr << c;
80 }
81 std::cerr << '\n';
82 }
83
84 void print() {
85 if(!enabled) return;
86
87 size_t nc = 0;
88 size_t total_mallocs = 0;
89 size_t total_frees = 0;
90 size_t overall_peak = 0;
91 for(size_t i = 0; i < passes_cnt; i++) {
92 nc = std::max(nc, std::strlen(passes[i].name));
93 total_mallocs += passes[i].mallocs;
94 total_frees += passes[i].frees;
95 overall_peak = std::max(overall_peak, passes[i].peak_allocs);
96 }
97 size_t nct = nc + 65;
98
99 const char * const title = "Heap Usage Statistic";
100 print('=', nct);
101 for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
102 std::cerr << title << std::endl;
103 print('-', nct);
104 std::cerr << std::setw(nc) << "Pass";
105 std::cerr << " | Malloc Count | Free Count | Peak Allocs |" << std::endl;
106
107 print('-', nct);
108 for(size_t i = 0; i < passes_cnt; i++) {
109 print(passes[i], nc, total_mallocs, total_frees, overall_peak);
110 }
111 print('-', nct);
112 print({"Sum", total_mallocs, total_frees, 0, overall_peak},
113 nc, total_mallocs, total_frees, overall_peak);
114
115 }
116
117#include <stdarg.h>
118#include <stddef.h>
119#include <stdio.h>
120#include <string.h>
121#include <unistd.h>
122#include <signal.h>
123 extern "C" {
124#include <dlfcn.h>
125#include <execinfo.h>
126 }
127
128 //=============================================================================================
129 // Interposing helpers
130 //=============================================================================================
131
132 typedef void (* generic_fptr_t)(void);
133 generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
134 const char * error;
135
136 static void * library;
137 if ( ! library ) {
138# if defined( RTLD_NEXT )
139 library = RTLD_NEXT;
140# else
141 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
142 library = dlopen( "libc.so.6", RTLD_LAZY );
143 error = dlerror();
144 if ( error ) {
145 std::cerr << "interpose_symbol : failed to open libc, " << error << std::endl;
146 abort();
147 }
148# endif // RTLD_NEXT
149 } // if
150
151 generic_fptr_t fptr;
152
153# if defined( _GNU_SOURCE )
154 if ( version ) {
155 fptr = (generic_fptr_t)dlvsym( library, symbol, version );
156 } else {
157 fptr = (generic_fptr_t)dlsym( library, symbol );
158 }
159# else
160 fptr = (generic_fptr_t)dlsym( library, symbol );
161# endif // _GNU_SOURCE
162
163 error = dlerror();
164 if ( error ) {
165 std::cerr << "interpose_symbol : internal error, " << error << std::endl;
166 abort();
167 }
168
169 return fptr;
170 }
171
172 extern "C" {
173 void * malloc( size_t size ) __attribute__((malloc));
174 void * malloc( size_t size ) {
175 static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr ));
176 if( enabled && passes_cnt > 0 ) {
177 passes[passes_cnt - 1].mallocs++;
178 passes[passes_cnt - 1].n_allocs++;
179 passes[passes_cnt - 1].peak_allocs
180 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
181 }
182 return __malloc( size );
183 }
184
185 void free( void * ptr ) {
186 static auto __free = reinterpret_cast<void (*)(void *)>(interpose_symbol( "free", nullptr ));
187 if( enabled && passes_cnt > 0 ) {
188 passes[passes_cnt - 1].frees++;
189 passes[passes_cnt - 1].n_allocs--;
190 }
191 return __free( ptr );
192 }
193
194 void * calloc( size_t nelem, size_t size ) {
195 static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr ));
196 if( enabled && passes_cnt > 0 ) {
197 passes[passes_cnt - 1].mallocs++;
198 passes[passes_cnt - 1].n_allocs++;
199 passes[passes_cnt - 1].peak_allocs
200 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
201 }
202 return __calloc( nelem, size );
203 }
204
205 void * realloc( void * ptr, size_t size ) {
206 static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr ));
207 void * s = __realloc( ptr, size );
208 if ( enabled && s != ptr && passes_cnt > 0 ) { // did realloc get new storage ?
209 passes[passes_cnt - 1].mallocs++;
210 passes[passes_cnt - 1].frees++;
211 } // if
212 return s;
213 }
214 }
215#endif
216 }
217}
Note: See TracBrowser for help on using the repository browser.