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 #include <vector>
17 
18 void *CurrentAllocator;
PostInitCallback()19 template <typename Config> void PostInitCallback() {
20   reinterpret_cast<scudo::Allocator<Config> *>(CurrentAllocator)->initGwpAsan();
21 }
22 
BM_malloc_free(benchmark::State & State)23 template <typename Config> static void BM_malloc_free(benchmark::State &State) {
24   using AllocatorT = scudo::Allocator<Config, PostInitCallback<Config>>;
25   auto Deleter = [](AllocatorT *A) {
26     A->unmapTestOnly();
27     delete A;
28   };
29   std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
30                                                            Deleter);
31   CurrentAllocator = Allocator.get();
32 
33   const size_t NBytes = State.range(0);
34   size_t PageSize = scudo::getPageSizeCached();
35 
36   for (auto _ : State) {
37     void *Ptr = Allocator->allocate(NBytes, scudo::Chunk::Origin::Malloc);
38     auto *Data = reinterpret_cast<uint8_t *>(Ptr);
39     for (size_t I = 0; I < NBytes; I += PageSize)
40       Data[I] = 1;
41     benchmark::DoNotOptimize(Ptr);
42     Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
43   }
44 
45   State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NBytes));
46 }
47 
48 static const size_t MinSize = 8;
49 static const size_t MaxSize = 128 * 1024;
50 
51 // FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
52 // cleanly.
53 BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidConfig)
54     ->Range(MinSize, MaxSize);
55 BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidSvelteConfig)
56     ->Range(MinSize, MaxSize);
57 #if SCUDO_CAN_USE_PRIMARY64
58 BENCHMARK_TEMPLATE(BM_malloc_free, scudo::FuchsiaConfig)
59     ->Range(MinSize, MaxSize);
60 #endif
61 
62 template <typename Config>
BM_malloc_free_loop(benchmark::State & State)63 static void BM_malloc_free_loop(benchmark::State &State) {
64   using AllocatorT = scudo::Allocator<Config, PostInitCallback<Config>>;
65   auto Deleter = [](AllocatorT *A) {
66     A->unmapTestOnly();
67     delete A;
68   };
69   std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
70                                                            Deleter);
71   CurrentAllocator = Allocator.get();
72 
73   const size_t NumIters = State.range(0);
74   size_t PageSize = scudo::getPageSizeCached();
75   std::vector<void *> Ptrs(NumIters);
76 
77   for (auto _ : State) {
78     size_t SizeLog2 = 0;
79     for (void *&Ptr : Ptrs) {
80       Ptr = Allocator->allocate(1 << SizeLog2, scudo::Chunk::Origin::Malloc);
81       auto *Data = reinterpret_cast<uint8_t *>(Ptr);
82       for (size_t I = 0; I < 1 << SizeLog2; I += PageSize)
83         Data[I] = 1;
84       benchmark::DoNotOptimize(Ptr);
85       SizeLog2 = (SizeLog2 + 1) % 16;
86     }
87     for (void *&Ptr : Ptrs)
88       Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
89   }
90 
91   State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NumIters) *
92                           8192);
93 }
94 
95 static const size_t MinIters = 8;
96 static const size_t MaxIters = 32 * 1024;
97 
98 // FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
99 // cleanly.
100 BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidConfig)
101     ->Range(MinIters, MaxIters);
102 BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidSvelteConfig)
103     ->Range(MinIters, MaxIters);
104 #if SCUDO_CAN_USE_PRIMARY64
105 BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::FuchsiaConfig)
106     ->Range(MinIters, MaxIters);
107 #endif
108 
109 BENCHMARK_MAIN();
110