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