source: src/Common/Stats/Heap.cc @ 4fa44e7

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 4fa44e7 was 120a28c3, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Added support for address-sanitizer which requires disabling Heap Statistics and TCMalloc

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