scudo: Add a basic malloc/free benchmark.

Differential Revision: https://reviews.llvm.org/D71104
This commit is contained in:
Peter Collingbourne 2019-12-05 16:44:07 -08:00
parent bab9849963
commit 29f0a65671
8 changed files with 162 additions and 0 deletions

View File

@ -133,6 +133,7 @@ if(COMPILER_RT_HAS_SCUDO_STANDALONE)
CFLAGS ${SCUDO_CFLAGS} CFLAGS ${SCUDO_CFLAGS}
PARENT_TARGET scudo_standalone) PARENT_TARGET scudo_standalone)
add_subdirectory(benchmarks)
if(COMPILER_RT_INCLUDE_TESTS) if(COMPILER_RT_INCLUDE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()

View File

@ -64,6 +64,7 @@ struct AndroidSvelteConfig {
using TSDRegistryT = TSDRegistrySharedT<A, 1U>; // Shared, only 1 TSD. using TSDRegistryT = TSDRegistrySharedT<A, 1U>; // Shared, only 1 TSD.
}; };
#if SCUDO_CAN_USE_PRIMARY64
struct FuchsiaConfig { struct FuchsiaConfig {
// 1GB Regions // 1GB Regions
typedef SizeClassAllocator64<DefaultSizeClassMap, 30U> Primary; typedef SizeClassAllocator64<DefaultSizeClassMap, 30U> Primary;
@ -71,6 +72,7 @@ struct FuchsiaConfig {
template <class A> template <class A>
using TSDRegistryT = TSDRegistrySharedT<A, 8U>; // Shared, max 8 TSDs. using TSDRegistryT = TSDRegistrySharedT<A, 8U>; // Shared, max 8 TSDs.
}; };
#endif
#if SCUDO_ANDROID #if SCUDO_ANDROID
typedef AndroidConfig Config; typedef AndroidConfig Config;

View File

@ -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
$<TARGET_OBJECTS:RTScudoStandalone.${arch}>)
set_property(TARGET ScudoBenchmarks.${arch} APPEND_STRING PROPERTY
COMPILE_FLAGS "${SCUDO_BENCHMARK_CFLAGS}")
endforeach()

View File

@ -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 <memory>
template <typename Config> static void BM_malloc_free(benchmark::State &State) {
using AllocatorT = scudo::Allocator<Config>;
auto Deleter = [](AllocatorT *A) {
A->unmapTestOnly();
delete A;
};
std::unique_ptr<AllocatorT, decltype(Deleter)> 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<uint8_t *>(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 <typename Config>
static void BM_malloc_free_loop(benchmark::State &State) {
using AllocatorT = scudo::Allocator<Config>;
auto Deleter = [](AllocatorT *A) {
A->unmapTestOnly();
delete A;
};
std::unique_ptr<AllocatorT, decltype(Deleter)> 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<uint8_t *>(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();

View File

@ -51,6 +51,7 @@ template <class Allocator, u32 MaxTSDCount> struct TSDRegistrySharedT {
unmap(reinterpret_cast<void *>(TSDs), unmap(reinterpret_cast<void *>(TSDs),
sizeof(TSD<Allocator>) * NumberOfTSDs); sizeof(TSD<Allocator>) * NumberOfTSDs);
setCurrentTSD(nullptr); setCurrentTSD(nullptr);
pthread_key_delete(PThreadKey);
} }
ALWAYS_INLINE void initThreadMaybe(Allocator *Instance, ALWAYS_INLINE void initThreadMaybe(Allocator *Instance,

View File

@ -15,6 +15,7 @@ group("scudo") {
deps = [] deps = []
foreach(toolchain, supported_toolchains) { foreach(toolchain, supported_toolchains) {
deps += [ deps += [
"standalone/benchmarks:ScudoBenchmarks($toolchain)",
"standalone/tests:ScudoCUnitTest($toolchain)", "standalone/tests:ScudoCUnitTest($toolchain)",
"standalone/tests:ScudoCxxUnitTest($toolchain)", "standalone/tests:ScudoCxxUnitTest($toolchain)",
"standalone/tests:ScudoUnitTest($toolchain)", "standalone/tests:ScudoUnitTest($toolchain)",

View File

@ -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",
]
}

View File

@ -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" ]
}