1a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany#include <stdio.h> 2a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany#include <vector> 3a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany#include <pthread.h> 4a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany#include <malloc.h> 5a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany#include <algorithm> 6a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany 7a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryanyusing namespace std; 8a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany 9a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryanyconst size_t kNumThreds = 16; 10abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukovconst size_t kNumIters = 1 << 23; 11a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany 123ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryanyinline void break_optimization(void *arg) { 133ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany __asm__ __volatile__("" : : "r" (arg) : "memory"); 143ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany} 153ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany 163ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany__attribute__((noinline)) 171045df665c7b314991fbdbe0eadd11b003574a04Kostya Serebryanystatic void *MallocThread(void *t) { 18a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t total_malloced = 0, total_freed = 0; 19a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t max_in_use = 0; 20a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t tid = reinterpret_cast<size_t>(t); 21a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany vector<pair<char *, size_t> > allocated; 22a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany allocated.reserve(kNumIters); 23a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany for (size_t i = 1; i < kNumIters; i++) { 24abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov if ((i % (kNumIters / 4)) == 0 && tid == 0) 25a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany fprintf(stderr, " T[%ld] iter %ld\n", tid, i); 26abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov bool allocate = (i % 5) <= 2; // 60% malloc, 40% free 27abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov if (i > kNumIters / 4) 28abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov allocate = i % 2; // then switch to 50% malloc, 50% free 29abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov if (allocate) { 30a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t size = 1 + (i % 200); 31a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany if ((i % 10001) == 0) 32a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size *= 4096; 33a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany total_malloced += size; 34a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany char *x = new char[size]; 35a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany x[0] = x[size - 1] = x[size / 2] = 0; 36a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany allocated.push_back(make_pair(x, size)); 37a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany max_in_use = max(max_in_use, total_malloced - total_freed); 38abb1febb6046fbc5fc30c7872dd06b27d0fb51f9Dmitry Vyukov } else { 39a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany if (allocated.empty()) continue; 40a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t slot = i % allocated.size(); 41a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany char *p = allocated[slot].first; 4209575a176caef64cf43f3eac8e197ee4f55572bdDmitry Vyukov p[0] = 0; // emulate last user touch of the block 43a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany size_t size = allocated[slot].second; 44a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany total_freed += size; 45a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany swap(allocated[slot], allocated.back()); 46a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany allocated.pop_back(); 47a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany delete [] p; 48a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany } 49a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany } 50a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany if (tid == 0) 51a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany fprintf(stderr, " T[%ld] total_malloced: %ldM in use %ldM max %ldM\n", 52a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany tid, total_malloced >> 20, (total_malloced - total_freed) >> 20, 53a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany max_in_use >> 20); 54a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany for (size_t i = 0; i < allocated.size(); i++) 55a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany delete [] allocated[i].first; 56a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany return 0; 57a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany} 58a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany 593ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryanytemplate <int depth> 603ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryanystruct DeepStack { 613ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany __attribute__((noinline)) 623ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany static void *run(void *t) { 633ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany break_optimization(0); 643ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany DeepStack<depth - 1>::run(t); 653ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany break_optimization(0); 663ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany return 0; 673ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany } 683ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany}; 693ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany 703ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryanytemplate<> 713ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryanystruct DeepStack<0> { 723ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany static void *run(void *t) { 733ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany MallocThread(t); 743ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany return 0; 753ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany } 763ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany}; 773ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany 781045df665c7b314991fbdbe0eadd11b003574a04Kostya Serebryany// Build with -Dstandalone_malloc_test=main to make it a separate program. 791045df665c7b314991fbdbe0eadd11b003574a04Kostya Serebryanyint standalone_malloc_test() { 80a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany pthread_t t[kNumThreds]; 81a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany for (size_t i = 0; i < kNumThreds; i++) 823ede807f3a02bdbcebf3e635bf2aeacf1c0082bdKostya Serebryany pthread_create(&t[i], 0, DeepStack<200>::run, reinterpret_cast<void *>(i)); 83a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany for (size_t i = 0; i < kNumThreds; i++) 84a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany pthread_join(t[i], 0); 85a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany malloc_stats(); 860b9218ab2b68401673c5d6225c9833bd58003ed4Kostya Serebryany return 0; 87a62440a464092ece8c068b57214ad3d13ec39b4bKostya Serebryany} 88