summaryrefslogtreecommitdiff
path: root/Userland/DevTools
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-05-23 12:52:19 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-23 19:31:39 +0200
commit39f073938138a722969b2933ffb577557613d64b (patch)
tree95f2d36d31e1a7d57e4745874240794d7725ca8f /Userland/DevTools
parentbd2b17a70e3df4f44c302b320b36ee08a972b896 (diff)
downloadserenity-39f073938138a722969b2933ffb577557613d64b.zip
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.
Diffstat (limited to 'Userland/DevTools')
-rw-r--r--Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp3
-rw-r--r--Userland/DevTools/UserspaceEmulator/MallocTracer.cpp50
-rw-r--r--Userland/DevTools/UserspaceEmulator/MallocTracer.h3
3 files changed, 39 insertions, 17 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp b/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp
index 33b0709c0f..63ef464052 100644
--- a/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp
+++ b/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp
@@ -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;
}
diff --git a/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp b/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp
index 4f00c21c52..c2c4a02303 100644
--- a/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp
+++ b/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp
@@ -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);
diff --git a/Userland/DevTools/UserspaceEmulator/MallocTracer.h b/Userland/DevTools/UserspaceEmulator/MallocTracer.h
index a294828e86..8d35d9ed04 100644
--- a/Userland/DevTools/UserspaceEmulator/MallocTracer.h
+++ b/Userland/DevTools/UserspaceEmulator/MallocTracer.h
@@ -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 {};