Changeset c02f761 for src/Common/Heap.cc


Ignore:
Timestamp:
May 4, 2018, 5:23:30 PM (6 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, with_gc
Children:
43c461d
Parents:
67db067
Message:

interpose allocation to gather statistics

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Common/Heap.cc

    r67db067 rc02f761  
    77// Heap.cc --
    88//
    9 // Author           : Peter A. Buhr
    10 // Created On       :
     9// Author           : Thierry Delisle
     10// Created On       : Thu May  3 16:16:10 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May  3 16:16:10 2018
    13 // Update Count     : 2
     12// Last Modified On : Fri May  4 17:17:59 2018
     13// Update Count     : 27
    1414//
    1515
     
    2121#include <iostream>
    2222
     23//#define WITH_HEAP_STATISTICS
     24
    2325namespace HeapStats {
    24         #if !defined( WITH_HEAP_STATISTICS )
    25                 void newPass( const char * const ) {}
     26#if !defined( WITH_HEAP_STATISTICS )
     27        void newPass( const char * const ) {}
    2628
    27                 void printStats() {}
    28         #else
    29                 struct StatBlock {
    30                         const char * name = nullptr;
    31                         size_t mallocs    = 0;
    32                         size_t frees      = 0;
    33                 };
     29        void printStats() {}
     30#else
     31        struct StatBlock {
     32                const char * name = nullptr;
     33                size_t mallocs    = 0;
     34                size_t frees      = 0;
     35        };
    3436
    35                 StatBlock    passes[100];
    36                 const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
    37                 size_t       passes_cnt = 0;
     37        StatBlock    passes[100] = {{ "Pre-Parse", 0, 0 }};
     38        const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
     39        size_t       passes_cnt = 1;
    3840
    39                 void newPass( const char * const name ) {
    40                         passes[passes_cnt].name    = name;
    41                         passes[passes_cnt].mallocs = 0;
    42                         passes[passes_cnt].frees   = 0;
    43                         passes_cnt++;
     41        void newPass( const char * const name ) {
     42                passes[passes_cnt].name    = name;
     43                passes[passes_cnt].mallocs = 0;
     44                passes[passes_cnt].frees   = 0;
     45                passes_cnt++;
    4446
    45                         assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h");
     47                assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h");
     48        }
     49
     50        void print(size_t value, size_t total) {
     51                std::cerr << std::setw(12) << value;
     52                std::cerr << "(" << std::setw(3);
     53                std::cerr << (value == 0 ? 0 : value * 100 / total);
     54                std::cerr << "%) | ";
     55        }
     56
     57        void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) {
     58                std::cerr << std::setw(nc) << stat.name;
     59                std::cerr << " | ";
     60
     61                print(stat.mallocs, total_mallocs);
     62                print(stat.frees  , total_frees  );
     63                std::cerr << "\n";
     64        }
     65
     66        void print(char c, size_t nc) {
     67                for(size_t i = 0; i < nc; i++) {
     68                        std::cerr << c;
     69                }
     70                std::cerr << '\n';
     71        }
     72
     73        void printStats() {
     74                size_t nc = 0;
     75                size_t total_mallocs = 0;
     76                size_t total_frees   = 0;
     77                for(size_t i = 0; i < passes_cnt; i++) {
     78                        nc = std::max(nc, std::strlen(passes[i].name));
     79                        total_mallocs += passes[i].mallocs;
     80                        total_frees   += passes[i].frees;
     81                }
     82                size_t nct = nc + 44;
     83
     84                const char * const title = "Heap Usage Statistic";
     85                print('=', nct);
     86                for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
     87                std::cerr << title << std::endl;
     88                print('-', nct);
     89                std::cerr << std::setw(nc) << "Pass";
     90                std::cerr << " |       Malloc Count |         Free Count |" << std::endl;
     91
     92                print('-', nct);
     93                for(size_t i = 0; i < passes_cnt; i++) {
     94                        print(passes[i], nc, total_mallocs, total_frees);
     95                }
     96                print('-', nct);
     97                print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees);
     98
     99        }
     100
     101#include <stdarg.h>
     102#include <stddef.h>
     103#include <stdio.h>
     104#include <string.h>
     105#include <unistd.h>
     106#include <signal.h>
     107        extern "C" {
     108#include <dlfcn.h>
     109#include <execinfo.h>
     110        }
     111
     112//=============================================================================================
     113// Interposing helpers
     114//=============================================================================================
     115
     116        typedef void (* generic_fptr_t)(void);
     117        generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
     118                const char * error;
     119
     120                static void * library;
     121                if ( ! library ) {
     122#if defined( RTLD_NEXT )
     123                        library = RTLD_NEXT;
     124#else
     125                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     126                        library = dlopen( "libc.so.6", RTLD_LAZY );
     127                        error = dlerror();
     128                        if ( error ) {
     129                                std::cerr << "interpose_symbol : failed to open libc, " << error << std::endl;
     130                                abort();
     131                        }
     132#endif
     133                } // if
     134
     135                generic_fptr_t fptr;
     136
     137#if defined( _GNU_SOURCE )
     138                if ( version ) {
     139                        fptr = (generic_fptr_t)dlvsym( library, symbol, version );
     140                } else {
     141                        fptr = (generic_fptr_t)dlsym( library, symbol );
     142                }
     143#else
     144                fptr = (generic_fptr_t)dlsym( library, symbol );
     145#endif // _GNU_SOURCE
     146
     147                error = dlerror();
     148                if ( error ) {
     149                        std::cerr << "interpose_symbol : internal error, " << error << std::endl;
     150                        abort();
    46151                }
    47152
    48                 void print(size_t value, size_t total) {
    49                         std::cerr << std::setw(12) << value;
    50                         std::cerr << "(" << std::setw(3);
    51                         std::cerr << (value == 0 ? 0 : value * 100 / total);
    52                         std::cerr << "%) | ";
     153                return fptr;
     154        }
     155
     156        extern "C" {
     157                void * malloc( size_t size ) __attribute__((malloc));
     158                void * malloc( size_t size ) {
     159                        static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr ));
     160                        if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
     161                        return __malloc( size );
    53162                }
    54163
    55                 void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) {
    56                         std::cerr << std::setw(nc) << stat.name;
    57                         std::cerr << " | ";
    58 
    59                         print(stat.mallocs, total_mallocs);
    60                         print(stat.frees  , total_frees  );
    61                         std::cerr << "\n";
     164                void free( void * ptr ) {
     165                        static auto __free = reinterpret_cast<void   (*)(void *)>(interpose_symbol( "free", nullptr ));
     166                        if( passes_cnt > 0 ) passes[passes_cnt - 1].frees++;
     167                        return __free( ptr );
    62168                }
    63169
    64                 void print(char c, size_t nc) {
    65                         for(size_t i = 0; i < nc; i++) {
    66                                 std::cerr << c;
    67                         }
    68                         std::cerr << '\n';
     170                void * calloc( size_t nelem, size_t size ) {
     171                        static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr ));
     172                        if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
     173                        return __calloc( nelem, size );
    69174                }
    70175
    71                 void printStats() {
    72                         size_t nc = 0;
    73                         size_t total_mallocs = 0;
    74                         size_t total_frees   = 0;
    75                         for(size_t i = 0; i < passes_cnt; i++) {
    76                                 nc = std::max(nc, std::strlen(passes[i].name));
    77                                 total_mallocs += passes[i].mallocs;
    78                                 total_frees   += passes[i].frees;
    79                         }
    80                         size_t nct = nc + 44;
    81 
    82                         const char * const title = "Heap Usage Statistic";
    83                         print('=', nct);
    84                         for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
    85                         std::cerr << title << std::endl;
    86                         print('-', nct);
    87                         std::cerr << std::setw(nc) << "Pass";
    88                         std::cerr << " |       Malloc Count |         Free Count |" << std::endl;
    89 
    90                         print('-', nct);
    91                         for(size_t i = 0; i < passes_cnt; i++) {
    92                                 print(passes[i], nc, total_mallocs, total_frees);
    93                         }
    94                         print('-', nct);
    95                         print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees);
    96 
     176                void * realloc( void * ptr, size_t size ) {
     177                        static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr ));
     178                        void * s = __realloc( ptr, size );
     179                        if ( s != ptr && passes_cnt > 0 ) {                     // did realloc get new storage ?
     180                                passes[passes_cnt - 1].mallocs++;
     181                                passes[passes_cnt - 1].frees++;
     182                        } // if
     183                        return s;
    97184                }
    98         #endif
     185        }
     186#endif
    99187}
    100 
Note: See TracChangeset for help on using the changeset viewer.