source: src/Common/Heap.cc @ b21c77a

new-env
Last change on this file since b21c77a was cdc4d43, checked in by Aaron Moss <a3moss@…>, 6 years ago

Fix leftover delete from last merge

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