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