source: src/Common/Stats/Heap.cc @ 7abee38

aaron-thesisarm-ehcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 7abee38 was 7abee38, checked in by tdelisle <tdelisle@…>, 4 years ago

Cleaned some module.mk files and preparing for better stats in the compiler

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