diff options
author | Vic Yang <victoryang@google.com> | 2019-01-29 20:23:16 -0800 |
---|---|---|
committer | Vic Yang <victoryang@google.com> | 2019-01-30 22:13:13 -0800 |
commit | bb7e1236f3676baffd5953061154e9a3552317d7 (patch) | |
tree | a1ddb820db657e34a56e66dd81a0b04a46922673 /linker/linker.cpp | |
parent | 58dd1cbd7f2a0b8a779f2f43c45447cdccc09c3e (diff) |
Purge linker block allocators before leaving linker
This is the second attempt to purge linker block allocators. Unlike the
previously reverted change which purge allocators whenever all objects
are freed, we only purge right before control leaves the linker. This
limits the performance impact to one munmap() call per dlopen(), in
most cases.
Bug: 112073665
Test: Boot and check memory usage with 'showmap'.
Test: Run camear cold start performance test.
Change-Id: I02c7c44935f768e065fbe7ff0389a84bd44713f0
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index d0c740baf..428dd25de 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -536,6 +536,10 @@ class SizeBasedAllocator { allocator_.free(ptr); } + static void purge() { + allocator_.purge(); + } + private: static LinkerBlockAllocator allocator_; }; @@ -553,6 +557,10 @@ class TypeBasedAllocator { static void free(T* ptr) { SizeBasedAllocator<sizeof(T)>::free(ptr); } + + static void purge() { + SizeBasedAllocator<sizeof(T)>::purge(); + } }; class LoadTask { @@ -2074,6 +2082,8 @@ void* do_dlopen(const char* name, int flags, ns == nullptr ? "(null)" : ns->get_name(), ns); + auto purge_guard = android::base::make_scope_guard([&]() { purge_unused_memory(); }); + auto failure_guard = android::base::make_scope_guard( [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); }); @@ -4069,3 +4079,17 @@ android_namespace_t* get_exported_namespace(const char* name) { } return it->second; } + +void purge_unused_memory() { + // For now, we only purge the memory used by LoadTask because we know those + // are temporary objects. + // + // Purging other LinkerBlockAllocator hardly yields much because they hold + // information about namespaces and opened libraries, which are not freed + // when the control leaves the linker. + // + // Purging BionicAllocator may give us a few dirty pages back, but those pages + // would be already zeroed out, so they compress easily in ZRAM. Therefore, + // it is not worth munmap()'ing those pages. + TypeBasedAllocator<LoadTask>::purge(); +} |