From 138b155042a03bff7d460657cf89a8e0da66234c Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 12 Mar 2013 08:44:40 +0000 Subject: [PATCH] [sanitizer] use fewer size classes in the allocator to reduce the memory footprint. There is no all-size-fits-all constant here, but this change is positive or neutral on several large apps I've tested llvm-svn: 176855 --- .../sanitizer_common/sanitizer_allocator.h | 52 ++++++++++--------- .../tests/sanitizer_allocator_test.cc | 6 +-- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h index 0a8d8452f805..6321d318760f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h @@ -26,15 +26,15 @@ namespace __sanitizer { // SizeClassMap maps allocation sizes into size classes and back. // Class 0 corresponds to size 0. // Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16). -// Next 8 classes: 256 + i * 32 (i = 1 to 8). -// Next 8 classes: 512 + i * 64 (i = 1 to 8). +// Next 4 classes: 256 + i * 64 (i = 1 to 4). +// Next 4 classes: 512 + i * 128 (i = 1 to 4). // ... -// Next 8 classes: 2^k + i * 2^(k-3) (i = 1 to 8). +// Next 4 classes: 2^k + i * 2^(k-2) (i = 1 to 4). // Last class corresponds to kMaxSize = 1 << kMaxSizeLog. // // This structure of the size class map gives us: // - Efficient table-free class-to-size and size-to-class functions. -// - Difference between two consequent size classes is betweed 12% and 6% +// - Difference between two consequent size classes is betweed 14% and 25% // // This class also gives a hint to a thread-caching allocator about the amount // of chunks that need to be cached per-thread: @@ -61,24 +61,28 @@ namespace __sanitizer { // c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15 // // c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16 -// c17 => s: 288 diff: +32 12% l 8 cached: 227 65376; id 17 -// c18 => s: 320 diff: +32 11% l 8 cached: 204 65280; id 18 -// c19 => s: 352 diff: +32 10% l 8 cached: 186 65472; id 19 -// c20 => s: 384 diff: +32 09% l 8 cached: 170 65280; id 20 -// c21 => s: 416 diff: +32 08% l 8 cached: 157 65312; id 21 -// c22 => s: 448 diff: +32 07% l 8 cached: 146 65408; id 22 -// c23 => s: 480 diff: +32 07% l 8 cached: 136 65280; id 23 +// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17 +// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18 +// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; id 19 // -// c24 => s: 512 diff: +32 06% l 9 cached: 128 65536; id 24 -// c25 => s: 576 diff: +64 12% l 9 cached: 113 65088; id 25 -// c26 => s: 640 diff: +64 11% l 9 cached: 102 65280; id 26 -// c27 => s: 704 diff: +64 10% l 9 cached: 93 65472; id 27 -// c28 => s: 768 diff: +64 09% l 9 cached: 85 65280; id 28 -// c29 => s: 832 diff: +64 08% l 9 cached: 78 64896; id 29 -// c30 => s: 896 diff: +64 07% l 9 cached: 73 65408; id 30 -// c31 => s: 960 diff: +64 07% l 9 cached: 68 65280; id 31 +// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20 +// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21 +// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22 +// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23 // -// c32 => s: 1024 diff: +64 06% l 10 cached: 64 65536; id 32 +// c24 => s: 1024 diff: +128 14% l 10 cached: 64 65536; id 24 +// c25 => s: 1280 diff: +256 25% l 10 cached: 51 65280; id 25 +// c26 => s: 1536 diff: +256 20% l 10 cached: 42 64512; id 26 +// c27 => s: 1792 diff: +256 16% l 10 cached: 36 64512; id 27 +// +// ... +// +// c48 => s: 65536 diff: +8192 14% l 16 cached: 1 65536; id 48 +// c49 => s: 81920 diff: +16384 25% l 16 cached: 1 81920; id 49 +// c50 => s: 98304 diff: +16384 20% l 16 cached: 1 98304; id 50 +// c51 => s: 114688 diff: +16384 16% l 16 cached: 1 114688; id 51 +// +// c52 => s: 131072 diff: +16384 14% l 17 cached: 1 131072; id 52 template class SizeClassMap { @@ -87,7 +91,7 @@ class SizeClassMap { static const uptr kMinSize = 1 << kMinSizeLog; static const uptr kMidSize = 1 << kMidSizeLog; static const uptr kMidClass = kMidSize / kMinSize; - static const uptr S = 3; + static const uptr S = 2; static const uptr M = (1 << S) - 1; public: @@ -185,10 +189,8 @@ class SizeClassMap { } }; -typedef SizeClassMap<17, 256, 16> - DefaultSizeClassMap; -typedef SizeClassMap<17, 64, 14> - CompactSizeClassMap; +typedef SizeClassMap<17, 256, 16> DefaultSizeClassMap; +typedef SizeClassMap<17, 64, 14> CompactSizeClassMap; template struct SizeClassAllocatorLocalCache; // Memory allocator statistics diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index 0e0d9a90e48b..40cf8a5190be 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -203,7 +203,7 @@ TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) { cache.Init(0); AllocatorStats stats; stats.Init(); - a->AllocateBatch(&stats, &cache, 64); + a->AllocateBatch(&stats, &cache, 32); EXPECT_EQ(TestMapUnmapCallback::map_count, 3); // State + alloc + metadata. a->TestOnlyUnmap(); EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); // The whole thing. @@ -225,7 +225,7 @@ TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) { cache.Init(0); AllocatorStats stats; stats.Init(); - a->AllocateBatch(&stats, &cache, 64); + a->AllocateBatch(&stats, &cache, 32); EXPECT_EQ(TestMapUnmapCallback::map_count, 2); // alloc. a->TestOnlyUnmap(); EXPECT_EQ(TestMapUnmapCallback::unmap_count, 2); // The whole thing + alloc. @@ -258,7 +258,7 @@ void FailInAssertionOnOOM() { AllocatorStats stats; stats.Init(); for (int i = 0; i < 1000000; i++) { - a.AllocateBatch(&stats, &cache, 64); + a.AllocateBatch(&stats, &cache, 52); } a.TestOnlyUnmap();