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();
102