From 785ce645e2ca8de868d121391d7ef70d1361ec5d Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 28 Nov 2018 16:55:50 -0800 Subject: [PATCH] pool allocators benchmark this benchmark shows that, as we expected, on Android mutexes, spinlocks and lock-free algorithms are running at similar performance. --- libs/utils/CMakeLists.txt | 1 + libs/utils/benchmark/benchmark_allocators.cpp | 116 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 libs/utils/benchmark/benchmark_allocators.cpp diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt index 52576fda8a..f1c0873954 100644 --- a/libs/utils/CMakeLists.txt +++ b/libs/utils/CMakeLists.txt @@ -127,6 +127,7 @@ add_library(benchmark_${TARGET}_callee SHARED benchmark/benchmark_callee.cpp) set(BENCHMARK_SRCS + benchmark/benchmark_allocators.cpp benchmark/benchmark_calls.cpp benchmark/benchmark_mutex.cpp benchmark/benchmark_memcpy.cpp) diff --git a/libs/utils/benchmark/benchmark_allocators.cpp b/libs/utils/benchmark/benchmark_allocators.cpp new file mode 100644 index 0000000000..b37e5c0232 --- /dev/null +++ b/libs/utils/benchmark/benchmark_allocators.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PerformanceCounters.h" + +#include +#include +#include + +#include + +using namespace utils; + + +class Allocators : public benchmark::Fixture { +public: + Allocators(); + ~Allocators() override; + +protected: + struct alignas(64) Payload {}; + + static_assert(sizeof(Payload) == 64, "Payload must be 64 bytes"); + + utils::Arena, LockingPolicy::NoLock> mPoolAllocatorNoLock; + utils::Arena, std::mutex> mPoolAllocatorStdMutex; + utils::Arena, utils::Mutex> mPoolAllocatorUtilsMutex; + utils::Arena, LockingPolicy::SpinLock> mPoolAllocatorSpinlock; + utils::Arena, LockingPolicy::NoLock> mPoolAllocatorAtomic; +}; + +static constexpr size_t POOL_ITEM_COUNT = 4096; + +Allocators::Allocators() + : mPoolAllocatorNoLock("nolock", POOL_ITEM_COUNT * sizeof(Payload)), + mPoolAllocatorStdMutex("std::mutex", POOL_ITEM_COUNT * sizeof(Payload)), + mPoolAllocatorUtilsMutex("utils::Mutex", POOL_ITEM_COUNT * sizeof(Payload)), + mPoolAllocatorSpinlock("spinlock", POOL_ITEM_COUNT * sizeof(Payload)), + mPoolAllocatorAtomic("atomic", POOL_ITEM_COUNT * sizeof(Payload)) { +} + +Allocators::~Allocators() = default; + +BENCHMARK_F(Allocators, poolAllocator_nolock)(benchmark::State& state) { + auto& pool = mPoolAllocatorNoLock; + PerformanceCounters pc(state); + for (auto _ : state) { + Payload* p = pool.alloc(1); + pool.free(p); + } +} + +BENCHMARK_DEFINE_F(Allocators, poolAllocator_std_mutex)(benchmark::State& state) { + auto& pool = mPoolAllocatorStdMutex; + PerformanceCounters pc(state); + for (auto _ : state) { + Payload* p = pool.alloc(1); + pool.free(p); + } +} + +BENCHMARK_DEFINE_F(Allocators, poolAllocator_utils_mutex)(benchmark::State& state) { + auto& pool = mPoolAllocatorUtilsMutex; + PerformanceCounters pc(state); + for (auto _ : state) { + Payload* p = pool.alloc(1); + pool.free(p); + } +} + +BENCHMARK_DEFINE_F(Allocators, poolAllocator_spinlock)(benchmark::State& state) { + auto& pool = mPoolAllocatorSpinlock; + PerformanceCounters pc(state); + for (auto _ : state) { + Payload* p = pool.alloc(1); + pool.free(p); + } +} + +BENCHMARK_DEFINE_F(Allocators, poolAllocator_atomic)(benchmark::State& state) { + auto& pool = mPoolAllocatorAtomic; + PerformanceCounters pc(state); + for (auto _ : state) { + Payload* p = pool.alloc(1); + pool.free(p); + } +} + +BENCHMARK_REGISTER_F(Allocators, poolAllocator_std_mutex) + ->ThreadRange(1, 4) + ->Threads(benchmark::CPUInfo::Get().num_cpus * 2); + +BENCHMARK_REGISTER_F(Allocators, poolAllocator_utils_mutex) + ->ThreadRange(1, 4) + ->Threads(benchmark::CPUInfo::Get().num_cpus * 2); + +BENCHMARK_REGISTER_F(Allocators, poolAllocator_spinlock) + ->ThreadRange(1, 4) + ->Threads(benchmark::CPUInfo::Get().num_cpus * 2); + +BENCHMARK_REGISTER_F(Allocators, poolAllocator_atomic) + ->ThreadRange(1, 4) + ->Threads(benchmark::CPUInfo::Get().num_cpus * 2);