13cab2bb3Spatrick //===-- malloc_benchmark.cpp ------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick
93cab2bb3Spatrick #include "allocator_config.h"
103cab2bb3Spatrick #include "combined.h"
113cab2bb3Spatrick #include "common.h"
123cab2bb3Spatrick
133cab2bb3Spatrick #include "benchmark/benchmark.h"
143cab2bb3Spatrick
153cab2bb3Spatrick #include <memory>
16*d89ec533Spatrick #include <vector>
17*d89ec533Spatrick
18*d89ec533Spatrick void *CurrentAllocator;
PostInitCallback()19*d89ec533Spatrick template <typename Config> void PostInitCallback() {
20*d89ec533Spatrick reinterpret_cast<scudo::Allocator<Config> *>(CurrentAllocator)->initGwpAsan();
21*d89ec533Spatrick }
223cab2bb3Spatrick
BM_malloc_free(benchmark::State & State)233cab2bb3Spatrick template <typename Config> static void BM_malloc_free(benchmark::State &State) {
24*d89ec533Spatrick using AllocatorT = scudo::Allocator<Config, PostInitCallback<Config>>;
253cab2bb3Spatrick auto Deleter = [](AllocatorT *A) {
263cab2bb3Spatrick A->unmapTestOnly();
273cab2bb3Spatrick delete A;
283cab2bb3Spatrick };
293cab2bb3Spatrick std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
303cab2bb3Spatrick Deleter);
31*d89ec533Spatrick CurrentAllocator = Allocator.get();
323cab2bb3Spatrick
333cab2bb3Spatrick const size_t NBytes = State.range(0);
343cab2bb3Spatrick size_t PageSize = scudo::getPageSizeCached();
353cab2bb3Spatrick
363cab2bb3Spatrick for (auto _ : State) {
373cab2bb3Spatrick void *Ptr = Allocator->allocate(NBytes, scudo::Chunk::Origin::Malloc);
383cab2bb3Spatrick auto *Data = reinterpret_cast<uint8_t *>(Ptr);
393cab2bb3Spatrick for (size_t I = 0; I < NBytes; I += PageSize)
403cab2bb3Spatrick Data[I] = 1;
413cab2bb3Spatrick benchmark::DoNotOptimize(Ptr);
423cab2bb3Spatrick Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
433cab2bb3Spatrick }
443cab2bb3Spatrick
453cab2bb3Spatrick State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NBytes));
463cab2bb3Spatrick }
473cab2bb3Spatrick
483cab2bb3Spatrick static const size_t MinSize = 8;
493cab2bb3Spatrick static const size_t MaxSize = 128 * 1024;
503cab2bb3Spatrick
513cab2bb3Spatrick // FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
523cab2bb3Spatrick // cleanly.
533cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidConfig)
543cab2bb3Spatrick ->Range(MinSize, MaxSize);
553cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free, scudo::AndroidSvelteConfig)
563cab2bb3Spatrick ->Range(MinSize, MaxSize);
573cab2bb3Spatrick #if SCUDO_CAN_USE_PRIMARY64
583cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free, scudo::FuchsiaConfig)
593cab2bb3Spatrick ->Range(MinSize, MaxSize);
603cab2bb3Spatrick #endif
613cab2bb3Spatrick
623cab2bb3Spatrick template <typename Config>
BM_malloc_free_loop(benchmark::State & State)633cab2bb3Spatrick static void BM_malloc_free_loop(benchmark::State &State) {
64*d89ec533Spatrick using AllocatorT = scudo::Allocator<Config, PostInitCallback<Config>>;
653cab2bb3Spatrick auto Deleter = [](AllocatorT *A) {
663cab2bb3Spatrick A->unmapTestOnly();
673cab2bb3Spatrick delete A;
683cab2bb3Spatrick };
693cab2bb3Spatrick std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
703cab2bb3Spatrick Deleter);
71*d89ec533Spatrick CurrentAllocator = Allocator.get();
723cab2bb3Spatrick
733cab2bb3Spatrick const size_t NumIters = State.range(0);
743cab2bb3Spatrick size_t PageSize = scudo::getPageSizeCached();
75*d89ec533Spatrick std::vector<void *> Ptrs(NumIters);
763cab2bb3Spatrick
773cab2bb3Spatrick for (auto _ : State) {
781f9cb04fSpatrick size_t SizeLog2 = 0;
793cab2bb3Spatrick for (void *&Ptr : Ptrs) {
801f9cb04fSpatrick Ptr = Allocator->allocate(1 << SizeLog2, scudo::Chunk::Origin::Malloc);
813cab2bb3Spatrick auto *Data = reinterpret_cast<uint8_t *>(Ptr);
821f9cb04fSpatrick for (size_t I = 0; I < 1 << SizeLog2; I += PageSize)
833cab2bb3Spatrick Data[I] = 1;
843cab2bb3Spatrick benchmark::DoNotOptimize(Ptr);
851f9cb04fSpatrick SizeLog2 = (SizeLog2 + 1) % 16;
863cab2bb3Spatrick }
873cab2bb3Spatrick for (void *&Ptr : Ptrs)
883cab2bb3Spatrick Allocator->deallocate(Ptr, scudo::Chunk::Origin::Malloc);
893cab2bb3Spatrick }
903cab2bb3Spatrick
913cab2bb3Spatrick State.SetBytesProcessed(uint64_t(State.iterations()) * uint64_t(NumIters) *
923cab2bb3Spatrick 8192);
933cab2bb3Spatrick }
943cab2bb3Spatrick
953cab2bb3Spatrick static const size_t MinIters = 8;
963cab2bb3Spatrick static const size_t MaxIters = 32 * 1024;
973cab2bb3Spatrick
983cab2bb3Spatrick // FIXME: Add DefaultConfig here once we can tear down the exclusive TSD
993cab2bb3Spatrick // cleanly.
1003cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidConfig)
1013cab2bb3Spatrick ->Range(MinIters, MaxIters);
1023cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::AndroidSvelteConfig)
1033cab2bb3Spatrick ->Range(MinIters, MaxIters);
1043cab2bb3Spatrick #if SCUDO_CAN_USE_PRIMARY64
1053cab2bb3Spatrick BENCHMARK_TEMPLATE(BM_malloc_free_loop, scudo::FuchsiaConfig)
1063cab2bb3Spatrick ->Range(MinIters, MaxIters);
1073cab2bb3Spatrick #endif
1083cab2bb3Spatrick
1093cab2bb3Spatrick BENCHMARK_MAIN();
110