template <bool kCount>
size_t ArenaAllocatorStatsImpl<kCount>::BytesAllocated() const { const size_t init = 0u; // Initial value of the correct type. return std::accumulate(alloc_stats_.begin(), alloc_stats_.end(), init);
}
template <bool kCount> void ArenaAllocatorStatsImpl<kCount>::Dump(std::ostream& os, const Arena* first,
ssize_t lost_bytes_adjustment) const {
size_t malloc_bytes = 0u;
size_t lost_bytes = 0u;
size_t num_arenas = 0u; for (const Arena* arena = first; arena != nullptr; arena = arena->next_) {
malloc_bytes += arena->Size();
lost_bytes += arena->RemainingSpace();
++num_arenas;
} // The lost_bytes_adjustment is used to make up for the fact that the current arena // may not have the bytes_allocated_ updated correctly.
lost_bytes += lost_bytes_adjustment; const size_t bytes_allocated = BytesAllocated();
os << " MEM: used: " << bytes_allocated << ", allocated: " << malloc_bytes
<< ", lost: " << lost_bytes << "\n";
size_t num_allocations = NumAllocations(); if (num_allocations != 0) {
os << "Number of arenas allocated: " << num_arenas << ", Number of allocations: "
<< num_allocations << ", avg size: " << bytes_allocated / num_allocations << "\n";
}
os << "===== Allocation by kind\n";
static_assert(arraysize(kAllocNames) == kNumArenaAllocKinds, "arraysize of kAllocNames"); for (int i = 0; i < kNumArenaAllocKinds; i++) { // Reduce output by listing only allocation kinds that actually have allocations. if (alloc_stats_[i] != 0u) {
os << kAllocNames[i] << std::setw(10) << alloc_stats_[i] << "\n";
}
}
}
#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winstantiation-after-specialization" // We're going to use ArenaAllocatorStatsImpl<kArenaAllocatorCountAllocations> which needs // to be explicitly instantiated if kArenaAllocatorCountAllocations is true. Explicit // instantiation of the specialization ArenaAllocatorStatsImpl<false> does not do anything // but requires the warning "-Winstantiation-after-specialization" to be turned off. // // To avoid bit-rot of the ArenaAllocatorStatsImpl<true>, instantiate it also in debug builds // (but keep the unnecessary code out of release builds) as we do not usually compile with // kArenaAllocatorCountAllocations set to true. templateclass ArenaAllocatorStatsImpl<kArenaAllocatorCountAllocations || kIsDebugBuild>; #pragma GCC diagnostic pop
void ArenaAllocator::UpdateBytesAllocated() { if (arena_head_ != nullptr) { // Update how many bytes we have allocated into the arena so that the arena pool knows how // much memory to zero out.
arena_head_->bytes_allocated_ = ptr_ - begin_;
}
}
void* ArenaAllocator::AllocWithMemoryTool(size_t bytes, ArenaAllocKind kind) { // We mark all memory for a newly retrieved arena as inaccessible and then // mark only the actually allocated memory as defined. That leaves red zones // and padding between allocations marked as inaccessible.
size_t rounded_bytes = RoundUp(bytes + kMemoryToolRedZoneBytes, 8);
ArenaAllocatorStats::RecordAlloc(rounded_bytes, kind);
uint8_t* ret; if (UNLIKELY(rounded_bytes > static_cast<size_t>(end_ - ptr_))) {
ret = AllocFromNewArenaWithMemoryTool(rounded_bytes);
} else {
ret = ptr_;
ptr_ += rounded_bytes;
}
MEMORY_TOOL_MAKE_DEFINED(ret, bytes); // Check that the memory is already zeroed out.
DCHECK(std::all_of(ret, ret + bytes, [](uint8_t val) { return val == 0u; })); return ret;
}
void* ArenaAllocator::AllocWithMemoryToolAlign16(size_t bytes, ArenaAllocKind kind) { // We mark all memory for a newly retrieved arena as inaccessible and then // mark only the actually allocated memory as defined. That leaves red zones // and padding between allocations marked as inaccessible.
size_t rounded_bytes = bytes + kMemoryToolRedZoneBytes;
DCHECK_ALIGNED(rounded_bytes, 8); // `bytes` is 16-byte aligned, red zone is 8-byte aligned.
uintptr_t padding =
RoundUp(reinterpret_cast<uintptr_t>(ptr_), 16) - reinterpret_cast<uintptr_t>(ptr_);
ArenaAllocatorStats::RecordAlloc(rounded_bytes, kind);
uint8_t* ret; if (UNLIKELY(padding + rounded_bytes > static_cast<size_t>(end_ - ptr_))) {
static_assert(kArenaAlignment >= 16, "Expecting sufficient alignment for new Arena.");
ret = AllocFromNewArenaWithMemoryTool(rounded_bytes);
} else {
ptr_ += padding; // Leave padding inaccessible.
ret = ptr_;
ptr_ += rounded_bytes;
}
MEMORY_TOOL_MAKE_DEFINED(ret, bytes); // Check that the memory is already zeroed out.
DCHECK(std::all_of(ret, ret + bytes, [](uint8_t val) { return val == 0u; })); return ret;
}
ArenaAllocator::~ArenaAllocator() { // Reclaim all the arenas by giving them back to the thread pool.
UpdateBytesAllocated();
pool_->FreeArenaChain(arena_head_);
}
uint8_t* ArenaAllocator::AllocFromNewArena(size_t bytes) {
Arena* new_arena = pool_->AllocArena(std::max(arena_allocator::kArenaDefaultSize, bytes));
DCHECK(new_arena != nullptr);
DCHECK_LE(bytes, new_arena->Size()); if (static_cast<size_t>(end_ - ptr_) > new_arena->Size() - bytes) { // The old arena has more space remaining than the new one, so keep using it. // This can happen when the requested size is over half of the default size.
DCHECK(arena_head_ != nullptr);
new_arena->bytes_allocated_ = bytes; // UpdateBytesAllocated() on the new_arena.
new_arena->next_ = arena_head_->next_;
arena_head_->next_ = new_arena;
} else {
UpdateBytesAllocated();
new_arena->next_ = arena_head_;
arena_head_ = new_arena; // Update our internal data structures.
begin_ = new_arena->Begin();
DCHECK_ALIGNED(begin_, kAlignment);
ptr_ = begin_ + bytes;
end_ = new_arena->End();
} return new_arena->Begin();
}
uint8_t* ArenaAllocator::AllocFromNewArenaWithMemoryTool(size_t bytes) {
uint8_t* ret = AllocFromNewArena(bytes);
uint8_t* noaccess_begin = ret + bytes;
uint8_t* noaccess_end; if (ret == arena_head_->Begin()) {
DCHECK(ptr_ - bytes == ret);
noaccess_end = end_;
} else { // We're still using the old arena but `ret` comes from a new one just after it.
DCHECK(arena_head_->next_ != nullptr);
DCHECK(ret == arena_head_->next_->Begin());
DCHECK_EQ(bytes, arena_head_->next_->GetBytesAllocated());
noaccess_end = arena_head_->next_->End();
}
MEMORY_TOOL_MAKE_NOACCESS(noaccess_begin, noaccess_end - noaccess_begin); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.