forked from OSchip/llvm-project
[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
This commit is contained in:
parent
26d5bc7fdf
commit
138b155042
|
@ -26,15 +26,15 @@ namespace __sanitizer {
|
||||||
// SizeClassMap maps allocation sizes into size classes and back.
|
// SizeClassMap maps allocation sizes into size classes and back.
|
||||||
// Class 0 corresponds to size 0.
|
// Class 0 corresponds to size 0.
|
||||||
// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
|
// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
|
||||||
// Next 8 classes: 256 + i * 32 (i = 1 to 8).
|
// Next 4 classes: 256 + i * 64 (i = 1 to 4).
|
||||||
// Next 8 classes: 512 + i * 64 (i = 1 to 8).
|
// 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.
|
// Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
|
||||||
//
|
//
|
||||||
// This structure of the size class map gives us:
|
// This structure of the size class map gives us:
|
||||||
// - Efficient table-free class-to-size and size-to-class functions.
|
// - 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
|
// This class also gives a hint to a thread-caching allocator about the amount
|
||||||
// of chunks that need to be cached per-thread:
|
// 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
|
// 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
|
// 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
|
// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17
|
||||||
// c18 => s: 320 diff: +32 11% l 8 cached: 204 65280; id 18
|
// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18
|
||||||
// c19 => s: 352 diff: +32 10% l 8 cached: 186 65472; id 19
|
// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; 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
|
|
||||||
//
|
//
|
||||||
// c24 => s: 512 diff: +32 06% l 9 cached: 128 65536; id 24
|
// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20
|
||||||
// c25 => s: 576 diff: +64 12% l 9 cached: 113 65088; id 25
|
// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21
|
||||||
// c26 => s: 640 diff: +64 11% l 9 cached: 102 65280; id 26
|
// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22
|
||||||
// c27 => s: 704 diff: +64 10% l 9 cached: 93 65472; id 27
|
// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23
|
||||||
// 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
|
|
||||||
//
|
//
|
||||||
// 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 <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog>
|
template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog>
|
||||||
class SizeClassMap {
|
class SizeClassMap {
|
||||||
|
@ -87,7 +91,7 @@ class SizeClassMap {
|
||||||
static const uptr kMinSize = 1 << kMinSizeLog;
|
static const uptr kMinSize = 1 << kMinSizeLog;
|
||||||
static const uptr kMidSize = 1 << kMidSizeLog;
|
static const uptr kMidSize = 1 << kMidSizeLog;
|
||||||
static const uptr kMidClass = kMidSize / kMinSize;
|
static const uptr kMidClass = kMidSize / kMinSize;
|
||||||
static const uptr S = 3;
|
static const uptr S = 2;
|
||||||
static const uptr M = (1 << S) - 1;
|
static const uptr M = (1 << S) - 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -185,10 +189,8 @@ class SizeClassMap {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SizeClassMap<17, 256, 16>
|
typedef SizeClassMap<17, 256, 16> DefaultSizeClassMap;
|
||||||
DefaultSizeClassMap;
|
typedef SizeClassMap<17, 64, 14> CompactSizeClassMap;
|
||||||
typedef SizeClassMap<17, 64, 14>
|
|
||||||
CompactSizeClassMap;
|
|
||||||
template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;
|
template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;
|
||||||
|
|
||||||
// Memory allocator statistics
|
// Memory allocator statistics
|
||||||
|
|
|
@ -203,7 +203,7 @@ TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
|
||||||
cache.Init(0);
|
cache.Init(0);
|
||||||
AllocatorStats stats;
|
AllocatorStats stats;
|
||||||
stats.Init();
|
stats.Init();
|
||||||
a->AllocateBatch(&stats, &cache, 64);
|
a->AllocateBatch(&stats, &cache, 32);
|
||||||
EXPECT_EQ(TestMapUnmapCallback::map_count, 3); // State + alloc + metadata.
|
EXPECT_EQ(TestMapUnmapCallback::map_count, 3); // State + alloc + metadata.
|
||||||
a->TestOnlyUnmap();
|
a->TestOnlyUnmap();
|
||||||
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); // The whole thing.
|
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); // The whole thing.
|
||||||
|
@ -225,7 +225,7 @@ TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
|
||||||
cache.Init(0);
|
cache.Init(0);
|
||||||
AllocatorStats stats;
|
AllocatorStats stats;
|
||||||
stats.Init();
|
stats.Init();
|
||||||
a->AllocateBatch(&stats, &cache, 64);
|
a->AllocateBatch(&stats, &cache, 32);
|
||||||
EXPECT_EQ(TestMapUnmapCallback::map_count, 2); // alloc.
|
EXPECT_EQ(TestMapUnmapCallback::map_count, 2); // alloc.
|
||||||
a->TestOnlyUnmap();
|
a->TestOnlyUnmap();
|
||||||
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 2); // The whole thing + alloc.
|
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 2); // The whole thing + alloc.
|
||||||
|
@ -258,7 +258,7 @@ void FailInAssertionOnOOM() {
|
||||||
AllocatorStats stats;
|
AllocatorStats stats;
|
||||||
stats.Init();
|
stats.Init();
|
||||||
for (int i = 0; i < 1000000; i++) {
|
for (int i = 0; i < 1000000; i++) {
|
||||||
a.AllocateBatch(&stats, &cache, 64);
|
a.AllocateBatch(&stats, &cache, 52);
|
||||||
}
|
}
|
||||||
|
|
||||||
a.TestOnlyUnmap();
|
a.TestOnlyUnmap();
|
||||||
|
|
Loading…
Reference in New Issue