diff options
| author | android-build-team Robot <android-build-team-robot@google.com> | 2019-04-10 03:04:31 +0000 |
|---|---|---|
| committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-04-10 03:04:31 +0000 |
| commit | 4211f30cb2d5ce6c0036564f98f3f11f3f531479 (patch) | |
| tree | 6389a4b1db7935c8139dcf2d5b150559ea370a9e | |
| parent | ccbdb6dbce67cf7bff98ae9a59dfee2466e184bf (diff) | |
| parent | c8c4babc33a84dabba513d4b7243f1dd3d2ea443 (diff) | |
Snap for 5452883 from c8c4babc33a84dabba513d4b7243f1dd3d2ea443 to qt-release
Change-Id: I67f564b0c54bb05662ffe4ca66909fc49d13cdbf
| -rw-r--r-- | benchmarks/malloc_benchmark.cpp | 13 | ||||
| -rw-r--r-- | benchmarks/stdlib_benchmark.cpp | 109 | ||||
| -rw-r--r-- | libc/Android.bp | 3 | ||||
| -rw-r--r-- | libc/bionic/malloc_common_dynamic.cpp | 37 | ||||
| -rw-r--r-- | libdl/Android.bp | 1 |
5 files changed, 149 insertions, 14 deletions
diff --git a/benchmarks/malloc_benchmark.cpp b/benchmarks/malloc_benchmark.cpp index 2fa1c87fd..ca54f11e3 100644 --- a/benchmarks/malloc_benchmark.cpp +++ b/benchmarks/malloc_benchmark.cpp @@ -102,22 +102,27 @@ void BenchmarkMalloc(MallocEntry entries[], size_t total_entries, size_t max_all // bionic/libc/malloc_debug/tools/gen_malloc.pl -i <THREAD_ID> g_sql_entries kMaxSqlAllocSlots < <ALLOC_FILE> > malloc_sql.h #include "malloc_sql.h" -static void BM_malloc_sql_trace_decay_time_0(benchmark::State& state) { +static void BM_malloc_sql_trace_default(benchmark::State& state) { + // The default is expected to be a zero decay time. mallopt(M_DECAY_TIME, 0); + for (auto _ : state) { BenchmarkMalloc(g_sql_entries, sizeof(g_sql_entries) / sizeof(MallocEntry), kMaxSqlAllocSlots); } } -BIONIC_BENCHMARK(BM_malloc_sql_trace_decay_time_0); +BIONIC_BENCHMARK(BM_malloc_sql_trace_default); -static void BM_malloc_sql_trace_decay_time_1(benchmark::State& state) { +static void BM_malloc_sql_trace_decay1(benchmark::State& state) { mallopt(M_DECAY_TIME, 1); + for (auto _ : state) { BenchmarkMalloc(g_sql_entries, sizeof(g_sql_entries) / sizeof(MallocEntry), kMaxSqlAllocSlots); } + + mallopt(M_DECAY_TIME, 0); } -BIONIC_BENCHMARK(BM_malloc_sql_trace_decay_time_1); +BIONIC_BENCHMARK(BM_malloc_sql_trace_decay1); #endif diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp index 7330dc423..6afe7aa57 100644 --- a/benchmarks/stdlib_benchmark.cpp +++ b/benchmarks/stdlib_benchmark.cpp @@ -17,30 +17,120 @@ #include <err.h> #include <langinfo.h> #include <locale.h> +#include <malloc.h> #include <stdlib.h> #include <unistd.h> #include <benchmark/benchmark.h> #include "util.h" -static void BM_stdlib_malloc_free(benchmark::State& state) { +#if defined(__BIONIC__) + +#else +#endif + +static __always_inline void MakeAllocationResident(void* ptr, size_t nbytes, int pagesize) { + uint8_t* data = reinterpret_cast<uint8_t*>(ptr); + for (size_t i = 0; i < nbytes; i += pagesize) { + data[i] = 1; + } +} + +static void MallocFree(benchmark::State& state) { const size_t nbytes = state.range(0); int pagesize = getpagesize(); - void* ptr; for (auto _ : state) { - ptr = malloc(nbytes); - // Make the entire allocation resident. - uint8_t* data = reinterpret_cast<uint8_t*>(ptr); - for (size_t i = 0; i < nbytes; i += pagesize) { - data[i] = 1; - } + void* ptr; + benchmark::DoNotOptimize(ptr = malloc(nbytes)); + MakeAllocationResident(ptr, nbytes, pagesize); free(ptr); } state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); } -BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free, "AT_COMMON_SIZES"); + +static void BM_stdlib_malloc_free_default(benchmark::State& state) { +#if defined(__BIONIC__) + // The default is expected to be a zero decay time. + mallopt(M_DECAY_TIME, 0); +#endif + + MallocFree(state); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_default, "AT_COMMON_SIZES"); + +#if defined(__BIONIC__) +static void BM_stdlib_malloc_free_decay1(benchmark::State& state) { + mallopt(M_DECAY_TIME, 1); + + MallocFree(state); + + mallopt(M_DECAY_TIME, 0); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_decay1, "AT_COMMON_SIZES"); +#endif + +static void MallocMultiple(benchmark::State& state, size_t nbytes, size_t numAllocs) { + int pagesize = getpagesize(); + void* ptrs[numAllocs]; + for (auto _ : state) { + for (size_t i = 0; i < numAllocs; i++) { + benchmark::DoNotOptimize(ptrs[i] = reinterpret_cast<uint8_t*>(malloc(nbytes))); + MakeAllocationResident(ptrs[i], nbytes, pagesize); + } + state.PauseTiming(); // Stop timers while freeing pointers. + for (size_t i = 0; i < numAllocs; i++) { + free(ptrs[i]); + } + state.ResumeTiming(); + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes) * numAllocs); +} + +void BM_stdlib_malloc_forty_default(benchmark::State& state) { + +#if defined(__BIONIC__) + // The default is expected to be a zero decay time. + mallopt(M_DECAY_TIME, 0); +#endif + + MallocMultiple(state, state.range(0), 40); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_default, "AT_COMMON_SIZES"); + +#if defined(__BIONIC__) +void BM_stdlib_malloc_forty_decay1(benchmark::State& state) { + mallopt(M_DECAY_TIME, 1); + + MallocMultiple(state, state.range(0), 40); + + mallopt(M_DECAY_TIME, 0); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_decay1, "AT_COMMON_SIZES"); +#endif + +void BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State& state) { +#if defined(__BIONIC__) + // The default is expected to be a zero decay time. + mallopt(M_DECAY_TIME, 0); +#endif + + MallocMultiple(state, 8192, state.range(0)); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_default, "AT_SMALL_SIZES"); + +#if defined(__BIONIC__) +void BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State& state) { + mallopt(M_DECAY_TIME, 1); + + MallocMultiple(state, 8192, state.range(0)); + + mallopt(M_DECAY_TIME, 0); +} +BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_decay1, "AT_SMALL_SIZES"); +#endif static void BM_stdlib_mbstowcs(benchmark::State& state) { const size_t buf_alignment = state.range(0); @@ -167,3 +257,4 @@ void BM_stdlib_strtoull(benchmark::State& state) { } } BIONIC_BENCHMARK(BM_stdlib_strtoull); + diff --git a/libc/Android.bp b/libc/Android.bp index 095066264..23ccbe3e9 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1578,6 +1578,9 @@ cc_library { "ld-android", "libdl", ], + static_libs: [ + "libdl_android", + ], whole_static_libs: [ "libjemalloc5", ], diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp index 3ccaed673..e7147a0e8 100644 --- a/libc/bionic/malloc_common_dynamic.cpp +++ b/libc/bionic/malloc_common_dynamic.cpp @@ -54,6 +54,8 @@ #include <stdlib.h> #include <unistd.h> +#include <android/dlext.h> + #include <private/bionic_config.h> #include <private/bionic_defs.h> #include <private/bionic_malloc_dispatch.h> @@ -277,8 +279,41 @@ bool InitSharedLibrary(void* impl_handle, const char* shared_lib, const char* pr return true; } +// Note about USE_SCUDO. This file is compiled into libc.so and libc_scudo.so. +// When compiled into libc_scudo.so, the libc_malloc_* libraries don't need +// to be loaded from the runtime namespace since libc_scudo.so is not from +// the runtime APEX, but is copied to any APEX that needs it. +#ifndef USE_SCUDO +extern "C" struct android_namespace_t* android_get_exported_namespace(const char* name); +#endif + void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) { - void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL); + void* impl_handle = nullptr; +#ifndef USE_SCUDO + // Try to load the libc_malloc_* libs from the "runtime" namespace and then + // fall back to dlopen() to load them from the default namespace. + // + // The libraries are packaged in the runtime APEX together with libc.so. + // However, since the libc.so is searched via the symlink in the system + // partition (/system/lib/libc.so -> /apex/com.android.runtime/bionic.libc.so) + // libc.so is loaded into the default namespace. If we just dlopen() here, the + // linker will load the libs found in /system/lib which might be incompatible + // with libc.so in the runtime APEX. Use android_dlopen_ext to explicitly load + // the ones in the runtime APEX. + struct android_namespace_t* runtime_ns = android_get_exported_namespace("runtime"); + if (runtime_ns != nullptr) { + const android_dlextinfo dlextinfo = { + .flags = ANDROID_DLEXT_USE_NAMESPACE, + .library_namespace = runtime_ns, + }; + impl_handle = android_dlopen_ext(shared_lib, RTLD_NOW | RTLD_LOCAL, &dlextinfo); + } +#endif + + if (impl_handle == nullptr) { + impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL); + } + if (impl_handle == nullptr) { error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror()); return nullptr; diff --git a/libdl/Android.bp b/libdl/Android.bp index a41aa2d2e..b1ee5ab22 100644 --- a/libdl/Android.bp +++ b/libdl/Android.bp @@ -114,6 +114,7 @@ cc_library { name: "libdl_android", defaults: ["linux_bionic_supported"], + recovery_available: true, // NOTE: --exclude-libs=libgcc.a makes sure that any symbols libdl.so pulls from // libgcc.a are made static to libdl.so. This in turn ensures that libraries that |
