diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt --- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -133,6 +133,7 @@ CFLAGS ${SCUDO_CFLAGS} PARENT_TARGET scudo_standalone) + add_subdirectory(benchmarks) if(COMPILER_RT_INCLUDE_TESTS) add_subdirectory(tests) endif() diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -64,6 +64,7 @@ using TSDRegistryT = TSDRegistrySharedT; // Shared, only 1 TSD. }; +#if SCUDO_CAN_USE_PRIMARY64 struct FuchsiaConfig { // 1GB Regions typedef SizeClassAllocator64 Primary; @@ -71,6 +72,7 @@ template using TSDRegistryT = TSDRegistrySharedT; // Shared, max 8 TSDs. }; +#endif #if SCUDO_ANDROID typedef AndroidConfig Config; diff --git a/compiler-rt/lib/scudo/standalone/benchmarks/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/benchmarks/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/benchmarks/CMakeLists.txt @@ -0,0 +1,21 @@ +# To build these benchmarks, build the target "ScudoBenchmarks.$ARCH", where +# $ARCH is the name of the target architecture. For example, +# ScudoBenchmarks.x86_64 for 64-bit x86. The benchmark executable is then +# available under projects/compiler-rt/lib/scudo/standalone/benchmarks/ in the +# build directory. + +include(AddLLVM) + +set(SCUDO_BENCHMARK_CFLAGS -I${COMPILER_RT_SOURCE_DIR}/lib/scudo/standalone) +if(ANDROID) + list(APPEND SCUDO_BENCHMARK_CFLAGS -fno-emulated-tls) +endif() +string(REPLACE ";" " " SCUDO_BENCHMARK_CFLAGS " ${SCUDO_BENCHMARK_CFLAGS}") + +foreach(arch ${SCUDO_STANDALONE_SUPPORTED_ARCH}) + add_benchmark(ScudoBenchmarks.${arch} + malloc_benchmark.cpp + $) + set_property(TARGET ScudoBenchmarks.${arch} APPEND_STRING PROPERTY + COMPILE_FLAGS "${SCUDO_BENCHMARK_CFLAGS}") +endforeach() diff --git a/compiler-rt/lib/scudo/standalone/benchmarks/malloc_benchmark.cpp b/compiler-rt/lib/scudo/standalone/benchmarks/malloc_benchmark.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/benchmarks/malloc_benchmark.cpp @@ -0,0 +1,101 @@ +//===-- malloc_benchmark.cpp ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "allocator_config.h" +#include "combined.h" +#include "common.h" + +#include "benchmark/benchmark.h" + +#include + +template static void BM_malloc_free(benchmark::State &State) { + using AllocatorT = scudo::Allocator; + auto Deleter = [](AllocatorT *A) { + A->unmapTestOnly(); + delete A; + }; + std::unique_ptr Allocator(new AllocatorT, + Deleter); + Allocator->reset(); + + const size_t NBytes = State.range(0); + size_t PageSize = scudo::getPageSizeCached(); + + for (auto _ : State) { + void *Ptr = Allocator->allocate(NBytes, scudo::Chunk::Origin::Malloc); + auto *Data = reinterpret_cast(Ptr); + for (size_t I = 0; I < NBytes; I += PageSize) + Data[I] = 1; + benchmark::DoNotOptimize(Ptr); + Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc); + } + + State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NBytes)); +} + +static const size_t MinSize = 8; +static const size_t MaxSize = 128 * 1024; + +// FIXME: Add DefaultConfig here once we can tear down the exclusive TSD +// cleanly. +BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidConfig) + ->Range(MinSize, MaxSize); +BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidSvelteConfig) + ->Range(MinSize, MaxSize); +#if SCUDO_CAN_USE_PRIMARY64 +BENCHMARK_TEMPLATE(BM_malloc_free, scudo::FuchsiaConfig) + ->Range(MinSize, MaxSize); +#endif + +template +static void BM_malloc_free_loop(benchmark::State &State) { + using AllocatorT = scudo::Allocator; + auto Deleter = [](AllocatorT *A) { + A->unmapTestOnly(); + delete A; + }; + std::unique_ptr Allocator(new AllocatorT, + Deleter); + Allocator->reset(); + + const size_t NumIters = State.range(0); + size_t PageSize = scudo::getPageSizeCached(); + void *Ptrs[NumIters]; + + for (auto _ : State) { + for (void *&Ptr : Ptrs) { + Ptr = Allocator->allocate(8192, scudo::Chunk::Origin::Malloc); + auto *Data = reinterpret_cast(Ptr); + for (size_t I = 0; I < 8192; I += PageSize) + Data[I] = 1; + benchmark::DoNotOptimize(Ptr); + } + for (void *&Ptr : Ptrs) + Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc); + } + + State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NumIters) * + 8192); +} + +static const size_t MinIters = 8; +static const size_t MaxIters = 32 * 1024; + +// FIXME: Add DefaultConfig here once we can tear down the exclusive TSD +// cleanly. +BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidConfig) + ->Range(MinIters, MaxIters); +BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidSvelteConfig) + ->Range(MinIters, MaxIters); +#if SCUDO_CAN_USE_PRIMARY64 +BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::FuchsiaConfig) + ->Range(MinIters, MaxIters); +#endif + +BENCHMARK_MAIN(); diff --git a/compiler-rt/lib/scudo/standalone/tsd_shared.h b/compiler-rt/lib/scudo/standalone/tsd_shared.h --- a/compiler-rt/lib/scudo/standalone/tsd_shared.h +++ b/compiler-rt/lib/scudo/standalone/tsd_shared.h @@ -51,6 +51,7 @@ unmap(reinterpret_cast(TSDs), sizeof(TSD) * NumberOfTSDs); setCurrentTSD(nullptr); + pthread_key_delete(PThreadKey); } ALWAYS_INLINE void initThreadMaybe(Allocator *Instance, diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/BUILD.gn --- a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/BUILD.gn @@ -15,6 +15,7 @@ deps = [] foreach(toolchain, supported_toolchains) { deps += [ + "standalone/benchmarks:ScudoBenchmarks($toolchain)", "standalone/tests:ScudoCUnitTest($toolchain)", "standalone/tests:ScudoCxxUnitTest($toolchain)", "standalone/tests:ScudoUnitTest($toolchain)", diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/benchmarks/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/benchmarks/BUILD.gn new file mode 100644 --- /dev/null +++ b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/benchmarks/BUILD.gn @@ -0,0 +1,10 @@ +executable("ScudoBenchmarks") { + configs += [ "//llvm/utils/gn/build:crt_code" ] + sources = [ + "malloc_benchmark.cpp", + ] + deps = [ + "//compiler-rt/lib/scudo/standalone:sources", + "//llvm/utils/benchmark", + ] +} diff --git a/llvm/utils/gn/secondary/llvm/utils/benchmark/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/benchmark/BUILD.gn new file mode 100644 --- /dev/null +++ b/llvm/utils/gn/secondary/llvm/utils/benchmark/BUILD.gn @@ -0,0 +1,25 @@ +static_library("benchmark") { + sources = [ + "src/benchmark.cc", + "src/benchmark_register.cc", + "src/colorprint.cc", + "src/commandlineflags.cc", + "src/complexity.cc", + "src/console_reporter.cc", + "src/counter.cc", + "src/csv_reporter.cc", + "src/json_reporter.cc", + "src/reporter.cc", + "src/sleep.cc", + "src/statistics.cc", + "src/string_util.cc", + "src/sysinfo.cc", + "src/timers.cc", + ] + deps = [ "//llvm/utils/gn/build/libs/pthread" ] + public_configs = [ ":benchmark_config" ] +} + +config("benchmark_config") { + include_dirs = [ "include" ] +}