Skip to content

Commit 29f0a65

Browse files
committed
scudo: Add a basic malloc/free benchmark.
Differential Revision: https://reviews.llvm.org/D71104
1 parent bab9849 commit 29f0a65

File tree

8 files changed

+162
-0
lines changed

8 files changed

+162
-0
lines changed

compiler-rt/lib/scudo/standalone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ if(COMPILER_RT_HAS_SCUDO_STANDALONE)
133133
CFLAGS ${SCUDO_CFLAGS}
134134
PARENT_TARGET scudo_standalone)
135135

136+
add_subdirectory(benchmarks)
136137
if(COMPILER_RT_INCLUDE_TESTS)
137138
add_subdirectory(tests)
138139
endif()

compiler-rt/lib/scudo/standalone/allocator_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,15 @@ struct AndroidSvelteConfig {
6464
using TSDRegistryT = TSDRegistrySharedT<A, 1U>; // Shared, only 1 TSD.
6565
};
6666

67+
#if SCUDO_CAN_USE_PRIMARY64
6768
struct FuchsiaConfig {
6869
// 1GB Regions
6970
typedef SizeClassAllocator64<DefaultSizeClassMap, 30U> Primary;
7071
typedef MapAllocator<0U> Secondary;
7172
template <class A>
7273
using TSDRegistryT = TSDRegistrySharedT<A, 8U>; // Shared, max 8 TSDs.
7374
};
75+
#endif
7476

7577
#if SCUDO_ANDROID
7678
typedef AndroidConfig Config;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# To build these benchmarks, build the target "ScudoBenchmarks.$ARCH", where
2+
# $ARCH is the name of the target architecture. For example,
3+
# ScudoBenchmarks.x86_64 for 64-bit x86. The benchmark executable is then
4+
# available under projects/compiler-rt/lib/scudo/standalone/benchmarks/ in the
5+
# build directory.
6+
7+
include(AddLLVM)
8+
9+
set(SCUDO_BENCHMARK_CFLAGS -I${COMPILER_RT_SOURCE_DIR}/lib/scudo/standalone)
10+
if(ANDROID)
11+
list(APPEND SCUDO_BENCHMARK_CFLAGS -fno-emulated-tls)
12+
endif()
13+
string(REPLACE ";" " " SCUDO_BENCHMARK_CFLAGS " ${SCUDO_BENCHMARK_CFLAGS}")
14+
15+
foreach(arch ${SCUDO_STANDALONE_SUPPORTED_ARCH})
16+
add_benchmark(ScudoBenchmarks.${arch}
17+
malloc_benchmark.cpp
18+
$<TARGET_OBJECTS:RTScudoStandalone.${arch}>)
19+
set_property(TARGET ScudoBenchmarks.${arch} APPEND_STRING PROPERTY
20+
COMPILE_FLAGS "${SCUDO_BENCHMARK_CFLAGS}")
21+
endforeach()
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//===-- malloc_benchmark.cpp ------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "allocator_config.h"
10+
#include "combined.h"
11+
#include "common.h"
12+
13+
#include "benchmark/benchmark.h"
14+
15+
#include <memory>
16+
17+
template <typename Config> static void BM_malloc_free(benchmark::State &State) {
18+
using AllocatorT = scudo::Allocator<Config>;
19+
auto Deleter = [](AllocatorT *A) {
20+
A->unmapTestOnly();
21+
delete A;
22+
};
23+
std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
24+
Deleter);
25+
Allocator->reset();
26+
27+
const size_t NBytes = State.range(0);
28+
size_t PageSize = scudo::getPageSizeCached();
29+
30+
for (auto _ : State) {
31+
void *Ptr = Allocator->allocate(NBytes, scudo::Chunk::Origin::Malloc);
32+
auto *Data = reinterpret_cast<uint8_t *>(Ptr);
33+
for (size_t I = 0; I < NBytes; I += PageSize)
34+
Data[I] = 1;
35+
benchmark::DoNotOptimize(Ptr);
36+
Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
37+
}
38+
39+
State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NBytes));
40+
}
41+
42+
static const size_t MinSize = 8;
43+
static const size_t MaxSize = 128 * 1024;
44+
45+
// FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
46+
// cleanly.
47+
BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidConfig)
48+
->Range(MinSize, MaxSize);
49+
BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidSvelteConfig)
50+
->Range(MinSize, MaxSize);
51+
#if SCUDO_CAN_USE_PRIMARY64
52+
BENCHMARK_TEMPLATE(BM_malloc_free, scudo::FuchsiaConfig)
53+
->Range(MinSize, MaxSize);
54+
#endif
55+
56+
template <typename Config>
57+
static void BM_malloc_free_loop(benchmark::State &State) {
58+
using AllocatorT = scudo::Allocator<Config>;
59+
auto Deleter = [](AllocatorT *A) {
60+
A->unmapTestOnly();
61+
delete A;
62+
};
63+
std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
64+
Deleter);
65+
Allocator->reset();
66+
67+
const size_t NumIters = State.range(0);
68+
size_t PageSize = scudo::getPageSizeCached();
69+
void *Ptrs[NumIters];
70+
71+
for (auto _ : State) {
72+
for (void *&Ptr : Ptrs) {
73+
Ptr = Allocator->allocate(8192, scudo::Chunk::Origin::Malloc);
74+
auto *Data = reinterpret_cast<uint8_t *>(Ptr);
75+
for (size_t I = 0; I < 8192; I += PageSize)
76+
Data[I] = 1;
77+
benchmark::DoNotOptimize(Ptr);
78+
}
79+
for (void *&Ptr : Ptrs)
80+
Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
81+
}
82+
83+
State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NumIters) *
84+
8192);
85+
}
86+
87+
static const size_t MinIters = 8;
88+
static const size_t MaxIters = 32 * 1024;
89+
90+
// FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
91+
// cleanly.
92+
BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidConfig)
93+
->Range(MinIters, MaxIters);
94+
BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidSvelteConfig)
95+
->Range(MinIters, MaxIters);
96+
#if SCUDO_CAN_USE_PRIMARY64
97+
BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::FuchsiaConfig)
98+
->Range(MinIters, MaxIters);
99+
#endif
100+
101+
BENCHMARK_MAIN();

compiler-rt/lib/scudo/standalone/tsd_shared.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ template <class Allocator, u32 MaxTSDCount> struct TSDRegistrySharedT {
5151
unmap(reinterpret_cast<void *>(TSDs),
5252
sizeof(TSD<Allocator>) * NumberOfTSDs);
5353
setCurrentTSD(nullptr);
54+
pthread_key_delete(PThreadKey);
5455
}
5556

5657
ALWAYS_INLINE void initThreadMaybe(Allocator *Instance,

llvm/utils/gn/secondary/compiler-rt/lib/scudo/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ group("scudo") {
1515
deps = []
1616
foreach(toolchain, supported_toolchains) {
1717
deps += [
18+
"standalone/benchmarks:ScudoBenchmarks($toolchain)",
1819
"standalone/tests:ScudoCUnitTest($toolchain)",
1920
"standalone/tests:ScudoCxxUnitTest($toolchain)",
2021
"standalone/tests:ScudoUnitTest($toolchain)",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
executable("ScudoBenchmarks") {
2+
configs += [ "//llvm/utils/gn/build:crt_code" ]
3+
sources = [
4+
"malloc_benchmark.cpp",
5+
]
6+
deps = [
7+
"//compiler-rt/lib/scudo/standalone:sources",
8+
"//llvm/utils/benchmark",
9+
]
10+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
static_library("benchmark") {
2+
sources = [
3+
"src/benchmark.cc",
4+
"src/benchmark_register.cc",
5+
"src/colorprint.cc",
6+
"src/commandlineflags.cc",
7+
"src/complexity.cc",
8+
"src/console_reporter.cc",
9+
"src/counter.cc",
10+
"src/csv_reporter.cc",
11+
"src/json_reporter.cc",
12+
"src/reporter.cc",
13+
"src/sleep.cc",
14+
"src/statistics.cc",
15+
"src/string_util.cc",
16+
"src/sysinfo.cc",
17+
"src/timers.cc",
18+
]
19+
deps = [ "//llvm/utils/gn/build/libs/pthread" ]
20+
public_configs = [ ":benchmark_config" ]
21+
}
22+
23+
config("benchmark_config") {
24+
include_dirs = [ "include" ]
25+
}

0 commit comments

Comments
 (0)