mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:57:44 +00:00
LibC+UE: Keep more unused chunked blocks around
Previously each malloc size class would keep around a limited number of unused blocks which were marked with MADV_SET_VOLATILE which could then be reinitialized when additional blocks were needed. This changes malloc() so that it also keeps around a number of blocks without marking them with MADV_SET_VOLATILE. I termed these "hot" blocks whereas blocks which were marked as MADV_SET_VOLATILE are called "cold" blocks because they're more expensive to reinitialize. In the worst case this could increase memory usage per process by 1MB when a program requests a bunch of memory and frees all of it. Also, in order to make more efficient use of these unused blocks they're now shared between size classes.
This commit is contained in:
parent
bd2b17a70e
commit
39f0739381
4 changed files with 93 additions and 35 deletions
|
@ -1121,6 +1121,9 @@ int Emulator::virt$emuctl(FlatPtr arg1, FlatPtr arg2, FlatPtr arg3)
|
|||
case 3:
|
||||
tracer->target_did_realloc({}, arg3, arg2);
|
||||
return 0;
|
||||
case 4:
|
||||
tracer->target_did_change_chunk_size({}, arg3, arg2);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,27 @@ inline void MallocTracer::for_each_mallocation(Callback callback) const
|
|||
});
|
||||
}
|
||||
|
||||
void MallocTracer::update_metadata(MmapRegion& mmap_region, size_t chunk_size)
|
||||
{
|
||||
mmap_region.set_malloc_metadata({},
|
||||
adopt_own(*new MallocRegionMetadata {
|
||||
.region = mmap_region,
|
||||
.address = mmap_region.base(),
|
||||
.chunk_size = chunk_size,
|
||||
.mallocations = {},
|
||||
}));
|
||||
auto& malloc_data = *mmap_region.malloc_metadata();
|
||||
|
||||
bool is_chunked_block = malloc_data.chunk_size <= size_classes[num_size_classes - 1];
|
||||
if (is_chunked_block)
|
||||
malloc_data.mallocations.resize((ChunkedBlock::block_size - sizeof(ChunkedBlock)) / malloc_data.chunk_size);
|
||||
else
|
||||
malloc_data.mallocations.resize(1);
|
||||
|
||||
// Mark the containing mmap region as a malloc block!
|
||||
mmap_region.set_malloc(true);
|
||||
}
|
||||
|
||||
void MallocTracer::target_did_malloc(Badge<Emulator>, FlatPtr address, size_t size)
|
||||
{
|
||||
if (m_emulator.is_in_loader_code())
|
||||
|
@ -59,29 +80,24 @@ void MallocTracer::target_did_malloc(Badge<Emulator>, FlatPtr address, size_t si
|
|||
|
||||
if (!mmap_region.is_malloc_block()) {
|
||||
auto chunk_size = mmap_region.read32(offsetof(CommonHeader, m_size)).value();
|
||||
mmap_region.set_malloc_metadata({},
|
||||
adopt_own(*new MallocRegionMetadata {
|
||||
.region = mmap_region,
|
||||
.address = mmap_region.base(),
|
||||
.chunk_size = chunk_size,
|
||||
.mallocations = {},
|
||||
}));
|
||||
auto& malloc_data = *mmap_region.malloc_metadata();
|
||||
|
||||
bool is_chunked_block = malloc_data.chunk_size <= size_classes[num_size_classes - 1];
|
||||
if (is_chunked_block)
|
||||
malloc_data.mallocations.resize((ChunkedBlock::block_size - sizeof(ChunkedBlock)) / malloc_data.chunk_size);
|
||||
else
|
||||
malloc_data.mallocations.resize(1);
|
||||
|
||||
// Mark the containing mmap region as a malloc block!
|
||||
mmap_region.set_malloc(true);
|
||||
update_metadata(mmap_region, chunk_size);
|
||||
}
|
||||
auto* mallocation = mmap_region.malloc_metadata()->mallocation_for_address(address);
|
||||
VERIFY(mallocation);
|
||||
*mallocation = { address, size, true, false, m_emulator.raw_backtrace(), Vector<FlatPtr>() };
|
||||
}
|
||||
|
||||
void MallocTracer::target_did_change_chunk_size(Badge<Emulator>, FlatPtr block, size_t chunk_size)
|
||||
{
|
||||
if (m_emulator.is_in_loader_code())
|
||||
return;
|
||||
auto* region = m_emulator.mmu().find_region({ 0x23, block });
|
||||
VERIFY(region);
|
||||
VERIFY(is<MmapRegion>(*region));
|
||||
auto& mmap_region = static_cast<MmapRegion&>(*region);
|
||||
update_metadata(mmap_region, chunk_size);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Mallocation* MallocRegionMetadata::mallocation_for_address(FlatPtr address) const
|
||||
{
|
||||
auto index = chunk_index_for_address(address);
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
void target_did_malloc(Badge<Emulator>, FlatPtr address, size_t);
|
||||
void target_did_free(Badge<Emulator>, FlatPtr address);
|
||||
void target_did_realloc(Badge<Emulator>, FlatPtr address, size_t);
|
||||
void target_did_change_chunk_size(Badge<Emulator>, FlatPtr, size_t);
|
||||
|
||||
void audit_read(const Region&, FlatPtr address, size_t);
|
||||
void audit_write(const Region&, FlatPtr address, size_t);
|
||||
|
@ -79,6 +80,8 @@ private:
|
|||
void dump_memory_graph();
|
||||
void populate_memory_graph();
|
||||
|
||||
void update_metadata(MmapRegion& mmap_region, size_t chunk_size);
|
||||
|
||||
Emulator& m_emulator;
|
||||
|
||||
MemoryGraph m_memory_graph {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue