1,釋放速度控制
在將一個Span刪除掉的時候,會優先將它加入到normal隊列中,這之后會嘗試從normal隊列中釋放一部分同樣大小的內存給系統。
釋放內存給系統的時候,tcmalloc使用了一個延時回收機制,如果這次一個page都沒釋放,那么默認要等1<<18個page(4k的page的話,是1GB)的釋放請求之后才會真正做釋放操作;如果這次釋放了n個page,那么要等1000 * n 個page釋放請求之后才會真正做釋放操作,這個地方有個上限,上限是1<<20個page(4k的page的話,是4GB)。
這樣做的原因,可能是想積攢若干個連續的頁再釋放,因為反復向操作系統釋放和申請內存是一個很重的操作。
2,每個線程cache的大小
默認情況下,每個線程的Cache上線是4MB:
static const size_t kMaxThreadCacheSize = 4 << 20;
每個線程的Cache下限是512KB
static const size_t kMinThreadCacheSize = kMaxSize * 2;
默認情況下,所有線程的Cache上限是32MB:
static const size_t kDefaultOverallThreadCacheSize = 8u * kMaxThreadCacheSize;
MallocExtension::GetStats的輸出:
MALLOC: 3966097008 ( 3782.4 MiB) Bytes in use by application
MALLOC: + 0 ( 0.0 MiB) Bytes in page heap freelist
MALLOC: + 25925136 ( 24.7 MiB) Bytes in central cache freelist
MALLOC: + 8526848 ( 8.1 MiB) Bytes in transfer cache freelist
MALLOC: + 24049536 ( 22.9 MiB) Bytes in thread cache freelists
MALLOC: + 18952344 ( 18.1 MiB) Bytes in malloc metadata
MALLOC: ------------
MALLOC: = 4043550872 ( 3856.2 MiB) Actual memory used (physical + swap)
MALLOC: + 8285011968 ( 7901.2 MiB) Bytes released to OS (aka unmapped)
MALLOC: ------------
MALLOC: = 12328562840 (11757.4 MiB) Virtual address space used
MALLOC:
MALLOC: 107257 Spans in use
MALLOC: 67 Thread heaps in use
MALLOC: 8192 Tcmalloc page size
各個數字的計算:
1, Virtual address space used
const uint64_t virtual_memory_used = (stats.pageheap.system_bytes // pageheap通過TCMalloc_SystemAlloc分配的內存
+ stats.metadata_bytes); // tcmalloc元數據占用的內存
stats.pageheap.system_bytes 內存只增不減,因為tcmalloc在內存不足時會優先利用madvise向OS釋放的內存
2,Actual memory used (physical + swap)
const uint64_t physical_memory_used = (virtual_memory_used
- stats.pageheap.unmapped_bytes); // 通過madvise向OS釋放的內存
Actual memory used 是指所有向系統申請的內存減去向系統釋放的內存。
3,Bytes in use by application:
const uint64_t bytes_in_use_by_app = (physical_memory_used
- stats.metadata_bytes
- stats.pageheap.free_bytes // pageheap所有normal隊列中的span長度之和
- stats.central_bytes
- stats.transfer_bytes
- stats.thread_bytes);
Bytes in use by application是指所有被應用使用的內存(所有物理內存減去所有Free list中的內存)。
Unmapped Bytes的含義是那些已經通過madvise釋放給操作系統,但是依然在returned鏈表上的span的長度之和。