分类: LINUX
2011-10-08 15:59:01
以上过程是span_allocator_.Init()函数的行为,到此已经分析完毕,下面我们继续看Static::InitStaticVars函数,次函数接着将会调用函数stacktrace_allocator_.Init();stacktrace_allocator_的定义如下,PageHeapAllocator
sizemap_.Init();
span_allocator_.Init();
span_allocator_.New(); // Reduce cache conflicts
span_allocator_.New(); // Reduce cache conflicts
stacktrace_allocator_.Init();
bucket_allocator_.Init();
// Do a bit of sanitizing: make sure central_cache is aligned properly
CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0);
for (int i = 0; i < kNumClasses; ++i) {
central_cache_[i].Init(i);
}
new ((void*)pageheap_memory_) PageHeap;
DLL_Init(&sampled_objects_);
Sampler::InitStatics();
}
后面开始初始化central_cache,central_cache作为整个tcmalloc的核心数据结构,他包含kNumClasses()个CentralFreeListPadded。每个CentralFreeListPadded以64bytes对齐,通过一个 char pad_[64 - kFreeListSizeMod64]来实现对齐。
template
private:
char pad_[64 - kFreeListSizeMod64];
};
template<>class CentralFreeListPaddedTo<0> : public CentralFreeList {
};
class CentralFreeListPadded : public CentralFreeListPaddedTo< sizeof(CentralFreeList) % 64> {
};
central_cache_的每个class都会通过调用下面的init函数进行初始化,init函数的调用参数为当前classnum,通过classnum初始化CentralFreeList的size_class_(本class的class num,通过class_to_size_可获得本class可以分配的最大obj的size)。DLL_Init只是简单的将span的next和prev指针指向自己。然后初始化counter_=0(Number of free objects in cache entry)。cache_size_和used_slots_的初始化和数据结构TCEntry tc_slots_[kNumTransferEntries]有关,TCEntry主要用来cache thread caches and the central cache之间的transfers of sizemap.num_objects_to_move(size_class)。 used_slots_代表现在正在使用中的tc_slots_数量,而cache_size_代表当前可使用的slots,当然这个数字可根据流量动态调整。
void CentralFreeList::Init(size_t cl) {
size_class_ = cl;
tcmalloc::DLL_Init(&empty_);
tcmalloc::DLL_Init(&nonempty_);
counter_ = 0;
cache_size_ = 1;
used_slots_ = 0;
ASSERT(cache_size_ <= kNumTransferEntries);
}
初始化完毕central_cache_后调用PageHeap的构造函数对char Static::pageheap_memory_[sizeof(PageHeap)]进行初始化。PageHeap的初始化函数如下所示,首先初始化pagemap_,page_map是一个三层的radix tree,他的初始化函数通过设置allocator为MetaDataAlloc,并利用MetaDataAlloc new出一个node作为root。pagemap_cache_是一个PackedCache
PageHeap::PageHeap()
: pagemap_(MetaDataAlloc),
pagemap_cache_(0),
scavenge_counter_(0),
// Start scavenging at kMaxPages list
release_index_(kMaxPages) {
COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
DLL_Init(&large_.normal);
DLL_Init(&large_.returned);
for (int i = 0; i < kMaxPages; i++) {
DLL_Init(&free_[i].normal);
DLL_Init(&free_[i].returned);
}
}