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 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> 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