1 #include <stdio.h> 2 #include <vector> 3 #include <pthread.h> 4 #include <malloc.h> 5 #include <algorithm> 6 7 using namespace std; 8 9 const size_t kNumThreds = 16; 10 const size_t kNumIters = 1 << 23; 11 12 inline void break_optimization(void *arg) { 13 __asm__ __volatile__("" : : "r" (arg) : "memory"); 14 } 15 16 __attribute__((noinline)) 17 static void *MallocThread(void *t) { 18 size_t total_malloced = 0, total_freed = 0; 19 size_t max_in_use = 0; 20 size_t tid = reinterpret_cast<size_t>(t); 21 vector<pair<char *, size_t> > allocated; 22 allocated.reserve(kNumIters); 23 for (size_t i = 1; i < kNumIters; i++) { 24 if ((i % (kNumIters / 4)) == 0 && tid == 0) 25 fprintf(stderr, " T[%ld] iter %ld\n", tid, i); 26 bool allocate = (i % 5) <= 2; // 60% malloc, 40% free 27 if (i > kNumIters / 4) 28 allocate = i % 2; // then switch to 50% malloc, 50% free 29 if (allocate) { 30 size_t size = 1 + (i % 200); 31 if ((i % 10001) == 0) 32 size *= 4096; 33 total_malloced += size; 34 char *x = new char[size]; 35 x[0] = x[size - 1] = x[size / 2] = 0; 36 allocated.push_back(make_pair(x, size)); 37 max_in_use = max(max_in_use, total_malloced - total_freed); 38 } else { 39 if (allocated.empty()) continue; 40 size_t slot = i % allocated.size(); 41 char *p = allocated[slot].first; 42 p[0] = 0; // emulate last user touch of the block 43 size_t size = allocated[slot].second; 44 total_freed += size; 45 swap(allocated[slot], allocated.back()); 46 allocated.pop_back(); 47 delete [] p; 48 } 49 } 50 if (tid == 0) 51 fprintf(stderr, " T[%ld] total_malloced: %ldM in use %ldM max %ldM\n", 52 tid, total_malloced >> 20, (total_malloced - total_freed) >> 20, 53 max_in_use >> 20); 54 for (size_t i = 0; i < allocated.size(); i++) 55 delete [] allocated[i].first; 56 return 0; 57 } 58 59 template <int depth> 60 struct DeepStack { 61 __attribute__((noinline)) 62 static void *run(void *t) { 63 break_optimization(0); 64 DeepStack<depth - 1>::run(t); 65 break_optimization(0); 66 return 0; 67 } 68 }; 69 70 template<> 71 struct DeepStack<0> { 72 static void *run(void *t) { 73 MallocThread(t); 74 return 0; 75 } 76 }; 77 78 // Build with -Dstandalone_malloc_test=main to make it a separate program. 79 int standalone_malloc_test() { 80 pthread_t t[kNumThreds]; 81 for (size_t i = 0; i < kNumThreds; i++) 82 pthread_create(&t[i], 0, DeepStack<200>::run, reinterpret_cast<void *>(i)); 83 for (size_t i = 0; i < kNumThreds; i++) 84 pthread_join(t[i], 0); 85 malloc_stats(); 86 return 0; 87 } 88