| 1 | /* |
| 2 | Copyright (c) 2005-2019 Intel Corporation |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #define MAX_THREADS 1024 |
| 18 | #define NUM_OF_BINS 30 |
| 19 | #define ThreadCommonCounters NUM_OF_BINS |
| 20 | |
| 21 | enum counter_type { |
| 22 | allocBlockNew = 0, |
| 23 | allocBlockPublic, |
| 24 | allocBumpPtrUsed, |
| 25 | allocFreeListUsed, |
| 26 | allocPrivatized, |
| 27 | examineEmptyEnough, |
| 28 | examineNotEmpty, |
| 29 | freeRestoreBumpPtr, |
| 30 | freeByOtherThread, |
| 31 | freeToActiveBlock, |
| 32 | freeToInactiveBlock, |
| 33 | freeBlockPublic, |
| 34 | freeBlockBack, |
| 35 | MaxCounters |
| 36 | }; |
| 37 | enum common_counter_type { |
| 38 | allocNewLargeObj = 0, |
| 39 | allocCachedLargeObj, |
| 40 | cacheLargeObj, |
| 41 | freeLargeObj, |
| 42 | lockPublicFreeList, |
| 43 | freeToOtherThread |
| 44 | }; |
| 45 | |
| 46 | #if COLLECT_STATISTICS |
| 47 | /* Statistics reporting callback registered via a static object dtor |
| 48 | on Posix or DLL_PROCESS_DETACH on Windows. |
| 49 | */ |
| 50 | |
| 51 | static bool reportAllocationStatistics; |
| 52 | |
| 53 | struct bin_counters { |
| 54 | int counter[MaxCounters]; |
| 55 | }; |
| 56 | |
| 57 | static bin_counters statistic[MAX_THREADS][NUM_OF_BINS+1]; //zero-initialized; |
| 58 | |
| 59 | static inline int STAT_increment(int thread, int bin, int ctr) |
| 60 | { |
| 61 | return reportAllocationStatistics && thread < MAX_THREADS ? ++(statistic[thread][bin].counter[ctr]) : 0; |
| 62 | } |
| 63 | |
| 64 | static inline void initStatisticsCollection() { |
| 65 | #if defined(MALLOCENV_COLLECT_STATISTICS) |
| 66 | if (NULL != getenv(MALLOCENV_COLLECT_STATISTICS)) |
| 67 | reportAllocationStatistics = true; |
| 68 | #endif |
| 69 | } |
| 70 | |
| 71 | #else |
| 72 | #define STAT_increment(a,b,c) ((void)0) |
| 73 | #endif /* COLLECT_STATISTICS */ |
| 74 | |
| 75 | #if COLLECT_STATISTICS |
| 76 | static inline void STAT_print(int thread) |
| 77 | { |
| 78 | if (!reportAllocationStatistics) |
| 79 | return; |
| 80 | |
| 81 | char filename[100]; |
| 82 | #if USE_PTHREAD |
| 83 | sprintf(filename, "stat_ScalableMalloc_proc%04d_thr%04d.log" , getpid(), thread); |
| 84 | #else |
| 85 | sprintf(filename, "stat_ScalableMalloc_thr%04d.log" , thread); |
| 86 | #endif |
| 87 | FILE* outfile = fopen(filename, "w" ); |
| 88 | for(int i=0; i<NUM_OF_BINS; ++i) |
| 89 | { |
| 90 | bin_counters& ctrs = statistic[thread][i]; |
| 91 | fprintf(outfile, "Thr%04d Bin%02d" , thread, i); |
| 92 | fprintf(outfile, ": allocNewBlocks %5d" , ctrs.counter[allocBlockNew]); |
| 93 | fprintf(outfile, ", allocPublicBlocks %5d" , ctrs.counter[allocBlockPublic]); |
| 94 | fprintf(outfile, ", restoreBumpPtr %5d" , ctrs.counter[freeRestoreBumpPtr]); |
| 95 | fprintf(outfile, ", privatizeCalled %10d" , ctrs.counter[allocPrivatized]); |
| 96 | fprintf(outfile, ", emptyEnough %10d" , ctrs.counter[examineEmptyEnough]); |
| 97 | fprintf(outfile, ", notEmptyEnough %10d" , ctrs.counter[examineNotEmpty]); |
| 98 | fprintf(outfile, ", freeBlocksPublic %5d" , ctrs.counter[freeBlockPublic]); |
| 99 | fprintf(outfile, ", freeBlocksBack %5d" , ctrs.counter[freeBlockBack]); |
| 100 | fprintf(outfile, "\n" ); |
| 101 | } |
| 102 | for(int i=0; i<NUM_OF_BINS; ++i) |
| 103 | { |
| 104 | bin_counters& ctrs = statistic[thread][i]; |
| 105 | fprintf(outfile, "Thr%04d Bin%02d" , thread, i); |
| 106 | fprintf(outfile, ": allocBumpPtr %10d" , ctrs.counter[allocBumpPtrUsed]); |
| 107 | fprintf(outfile, ", allocFreeList %10d" , ctrs.counter[allocFreeListUsed]); |
| 108 | fprintf(outfile, ", freeToActiveBlk %10d" , ctrs.counter[freeToActiveBlock]); |
| 109 | fprintf(outfile, ", freeToInactive %10d" , ctrs.counter[freeToInactiveBlock]); |
| 110 | fprintf(outfile, ", freedByOther %10d" , ctrs.counter[freeByOtherThread]); |
| 111 | fprintf(outfile, "\n" ); |
| 112 | } |
| 113 | bin_counters& ctrs = statistic[thread][ThreadCommonCounters]; |
| 114 | fprintf(outfile, "Thr%04d common counters" , thread); |
| 115 | fprintf(outfile, ": allocNewLargeObject %5d" , ctrs.counter[allocNewLargeObj]); |
| 116 | fprintf(outfile, ": allocCachedLargeObject %5d" , ctrs.counter[allocCachedLargeObj]); |
| 117 | fprintf(outfile, ", cacheLargeObject %5d" , ctrs.counter[cacheLargeObj]); |
| 118 | fprintf(outfile, ", freeLargeObject %5d" , ctrs.counter[freeLargeObj]); |
| 119 | fprintf(outfile, ", lockPublicFreeList %5d" , ctrs.counter[lockPublicFreeList]); |
| 120 | fprintf(outfile, ", freeToOtherThread %10d" , ctrs.counter[freeToOtherThread]); |
| 121 | fprintf(outfile, "\n" ); |
| 122 | |
| 123 | fclose(outfile); |
| 124 | } |
| 125 | #endif |
| 126 | |