common.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. // Copyright (c) 2008, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // ---
  31. // Author: Sanjay Ghemawat <opensource@google.com>
  32. #include <stdlib.h> // for getenv and strtol
  33. #include "config.h"
  34. #include "common.h"
  35. #include "system-alloc.h"
  36. #include "base/spinlock.h"
  37. #include "getenv_safe.h" // TCMallocGetenvSafe
  38. namespace tcmalloc {
  39. // Define the maximum number of object per classe type to transfer between
  40. // thread and central caches.
  41. static int32 FLAGS_tcmalloc_transfer_num_objects;
  42. static const int32 kDefaultTransferNumObjecs = 512;
  43. // The init function is provided to explicit initialize the variable value
  44. // from the env. var to avoid C++ global construction that might defer its
  45. // initialization after a malloc/new call.
  46. static inline void InitTCMallocTransferNumObjects()
  47. {
  48. if (UNLIKELY(FLAGS_tcmalloc_transfer_num_objects == 0)) {
  49. const char *envval = TCMallocGetenvSafe("TCMALLOC_TRANSFER_NUM_OBJ");
  50. FLAGS_tcmalloc_transfer_num_objects = !envval ? kDefaultTransferNumObjecs :
  51. strtol(envval, NULL, 10);
  52. }
  53. }
  54. // Note: the following only works for "n"s that fit in 32-bits, but
  55. // that is fine since we only use it for small sizes.
  56. static inline int LgFloor(size_t n) {
  57. int log = 0;
  58. for (int i = 4; i >= 0; --i) {
  59. int shift = (1 << i);
  60. size_t x = n >> shift;
  61. if (x != 0) {
  62. n = x;
  63. log += shift;
  64. }
  65. }
  66. ASSERT(n == 1);
  67. return log;
  68. }
  69. int AlignmentForSize(size_t size) {
  70. int alignment = kAlignment;
  71. if (size > kMaxSize) {
  72. // Cap alignment at kPageSize for large sizes.
  73. alignment = kPageSize;
  74. } else if (size >= 128) {
  75. // Space wasted due to alignment is at most 1/8, i.e., 12.5%.
  76. alignment = (1 << LgFloor(size)) / 8;
  77. } else if (size >= kMinAlign) {
  78. // We need an alignment of at least 16 bytes to satisfy
  79. // requirements for some SSE types.
  80. alignment = kMinAlign;
  81. }
  82. // Maximum alignment allowed is page size alignment.
  83. if (alignment > kPageSize) {
  84. alignment = kPageSize;
  85. }
  86. CHECK_CONDITION(size < kMinAlign || alignment >= kMinAlign);
  87. CHECK_CONDITION((alignment & (alignment - 1)) == 0);
  88. return alignment;
  89. }
  90. int SizeMap::NumMoveSize(size_t size) {
  91. if (size == 0) return 0;
  92. // Use approx 64k transfers between thread and central caches.
  93. int num = static_cast<int>(64.0 * 1024.0 / size);
  94. if (num < 2) num = 2;
  95. // Avoid bringing too many objects into small object free lists.
  96. // If this value is too large:
  97. // - We waste memory with extra objects sitting in the thread caches.
  98. // - The central freelist holds its lock for too long while
  99. // building a linked list of objects, slowing down the allocations
  100. // of other threads.
  101. // If this value is too small:
  102. // - We go to the central freelist too often and we have to acquire
  103. // its lock each time.
  104. // This value strikes a balance between the constraints above.
  105. if (num > FLAGS_tcmalloc_transfer_num_objects)
  106. num = FLAGS_tcmalloc_transfer_num_objects;
  107. return num;
  108. }
  109. // Initialize the mapping arrays
  110. void SizeMap::Init() {
  111. InitTCMallocTransferNumObjects();
  112. // Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
  113. if (ClassIndex(0) != 0) {
  114. Log(kCrash, __FILE__, __LINE__,
  115. "Invalid class index for size 0", ClassIndex(0));
  116. }
  117. if (ClassIndex(kMaxSize) >= sizeof(class_array_)) {
  118. Log(kCrash, __FILE__, __LINE__,
  119. "Invalid class index for kMaxSize", ClassIndex(kMaxSize));
  120. }
  121. // Compute the size classes we want to use
  122. int sc = 1; // Next size class to assign
  123. int alignment = kAlignment;
  124. CHECK_CONDITION(kAlignment <= kMinAlign);
  125. for (size_t size = kAlignment; size <= kMaxSize; size += alignment) {
  126. alignment = AlignmentForSize(size);
  127. CHECK_CONDITION((size % alignment) == 0);
  128. int blocks_to_move = NumMoveSize(size) / 4;
  129. size_t psize = 0;
  130. do {
  131. psize += kPageSize;
  132. // Allocate enough pages so leftover is less than 1/8 of total.
  133. // This bounds wasted space to at most 12.5%.
  134. while ((psize % size) > (psize >> 3)) {
  135. psize += kPageSize;
  136. }
  137. // Continue to add pages until there are at least as many objects in
  138. // the span as are needed when moving objects from the central
  139. // freelists and spans to the thread caches.
  140. } while ((psize / size) < (blocks_to_move));
  141. const size_t my_pages = psize >> kPageShift;
  142. if (sc > 1 && my_pages == class_to_pages_[sc-1]) {
  143. // See if we can merge this into the previous class without
  144. // increasing the fragmentation of the previous class.
  145. const size_t my_objects = (my_pages << kPageShift) / size;
  146. const size_t prev_objects = (class_to_pages_[sc-1] << kPageShift)
  147. / class_to_size_[sc-1];
  148. if (my_objects == prev_objects) {
  149. // Adjust last class to include this size
  150. class_to_size_[sc-1] = size;
  151. continue;
  152. }
  153. }
  154. // Add new class
  155. class_to_pages_[sc] = my_pages;
  156. class_to_size_[sc] = size;
  157. sc++;
  158. }
  159. if (sc != kNumClasses) {
  160. Log(kCrash, __FILE__, __LINE__,
  161. "wrong number of size classes: (found vs. expected )", sc, kNumClasses);
  162. }
  163. // Initialize the mapping arrays
  164. int next_size = 0;
  165. for (int c = 1; c < kNumClasses; c++) {
  166. const int max_size_in_class = class_to_size_[c];
  167. for (int s = next_size; s <= max_size_in_class; s += kAlignment) {
  168. class_array_[ClassIndex(s)] = c;
  169. }
  170. next_size = max_size_in_class + kAlignment;
  171. }
  172. // Double-check sizes just to be safe
  173. for (size_t size = 0; size <= kMaxSize;) {
  174. const int sc = SizeClass(size);
  175. if (sc <= 0 || sc >= kNumClasses) {
  176. Log(kCrash, __FILE__, __LINE__,
  177. "Bad size class (class, size)", sc, size);
  178. }
  179. if (sc > 1 && size <= class_to_size_[sc-1]) {
  180. Log(kCrash, __FILE__, __LINE__,
  181. "Allocating unnecessarily large class (class, size)", sc, size);
  182. }
  183. const size_t s = class_to_size_[sc];
  184. if (size > s || s == 0) {
  185. Log(kCrash, __FILE__, __LINE__,
  186. "Bad (class, size, requested)", sc, s, size);
  187. }
  188. if (size <= kMaxSmallSize) {
  189. size += 8;
  190. } else {
  191. size += 128;
  192. }
  193. }
  194. // Initialize the num_objects_to_move array.
  195. for (size_t cl = 1; cl < kNumClasses; ++cl) {
  196. num_objects_to_move_[cl] = NumMoveSize(ByteSizeForClass(cl));
  197. }
  198. }
  199. // Metadata allocator -- keeps stats about how many bytes allocated.
  200. static uint64_t metadata_system_bytes_ = 0;
  201. static const size_t kMetadataAllocChunkSize = 8*1024*1024;
  202. // As ThreadCache objects are allocated with MetaDataAlloc, and also
  203. // CACHELINE_ALIGNED, we must use the same alignment as TCMalloc_SystemAlloc.
  204. static const size_t kMetadataAllignment = sizeof(MemoryAligner);
  205. static char *metadata_chunk_alloc_;
  206. static size_t metadata_chunk_avail_;
  207. static SpinLock metadata_alloc_lock(SpinLock::LINKER_INITIALIZED);
  208. void* MetaDataAlloc(size_t bytes) {
  209. if (bytes >= kMetadataAllocChunkSize) {
  210. void *rv = TCMalloc_SystemAlloc(bytes,
  211. NULL, kMetadataAllignment);
  212. if (rv != NULL) {
  213. metadata_system_bytes_ += bytes;
  214. }
  215. return rv;
  216. }
  217. SpinLockHolder h(&metadata_alloc_lock);
  218. // the following works by essentially turning address to integer of
  219. // log_2 kMetadataAllignment size and negating it. I.e. negated
  220. // value + original value gets 0 and that's what we want modulo
  221. // kMetadataAllignment. Note, we negate before masking higher bits
  222. // off, otherwise we'd have to mask them off after negation anyways.
  223. intptr_t alignment = -reinterpret_cast<intptr_t>(metadata_chunk_alloc_) & (kMetadataAllignment-1);
  224. if (metadata_chunk_avail_ < bytes + alignment) {
  225. size_t real_size;
  226. void *ptr = TCMalloc_SystemAlloc(kMetadataAllocChunkSize,
  227. &real_size, kMetadataAllignment);
  228. if (ptr == NULL) {
  229. return NULL;
  230. }
  231. metadata_chunk_alloc_ = static_cast<char *>(ptr);
  232. metadata_chunk_avail_ = real_size;
  233. alignment = 0;
  234. }
  235. void *rv = static_cast<void *>(metadata_chunk_alloc_ + alignment);
  236. bytes += alignment;
  237. metadata_chunk_alloc_ += bytes;
  238. metadata_chunk_avail_ -= bytes;
  239. metadata_system_bytes_ += bytes;
  240. return rv;
  241. }
  242. uint64_t metadata_system_bytes() { return metadata_system_bytes_; }
  243. } // namespace tcmalloc