blob: c7fe316d911ea5314536dd7b5d3148c2af7fdf32 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/fdf/cpp/arena.h>
#include <lib/syslog/cpp/macros.h>
#include <vector>
#include <fbl/string_printf.h>
#include <perftest/perftest.h>
#include "src/devices/bin/driver_runtime/microbenchmarks/assert.h"
namespace {
// Measure the time taken to allocate and free a |buffer_size|-byte block.
bool ArenaAllocFreeTest(perftest::RepeatState* state, size_t buffer_size) {
constexpr uint32_t kTag = 'BNCH';
fdf::Arena arena(kTag);
state->DeclareStep("alloc");
state->DeclareStep("free");
while (state->KeepRunning()) {
void* block = arena.Allocate(buffer_size);
if (!block) {
return false;
}
state->NextStep();
arena.Free(block); // Currently a no-op.
}
return true;
}
// Measure the time taken to allocate a large block followed by a bunch of small
// ones.
bool ArenaAllocLargeThenSmallTest(perftest::RepeatState* state, size_t large_size) {
constexpr uint32_t kTag = 'BNCH';
fdf::Arena arena(kTag);
state->DeclareStep("one_large_block");
state->DeclareStep("fifty_small_blocks");
while (state->KeepRunning()) {
void* block = arena.Allocate(large_size);
if (!block) {
return false;
}
state->NextStep();
for (size_t i = 0; i < 50; i++) {
void* block = arena.Allocate(32);
if (!block) {
return false;
}
}
}
return true;
}
// Measure the time taken to check whether a block is contained in an arena
// which holds |num_blocks|.
bool ArenaContainsTest(perftest::RepeatState* state, uint32_t num_blocks) {
constexpr size_t kBlockSizeBytes = 0x1000;
constexpr uint32_t kTag = 'BNCH';
fdf::Arena arena(kTag);
std::vector<uint32_t*> allocated;
for (uint32_t i = 0; i < num_blocks; i++) {
auto data = static_cast<uint32_t*>(arena.Allocate(kBlockSizeBytes));
allocated.push_back(data);
}
uint32_t i = 0;
while (state->KeepRunning()) {
FX_CHECK(arena.Contains(allocated[i]));
i++;
i %= allocated.size();
}
return true;
}
void RegisterTests() {
static const unsigned kBlockSize[] = {
32, 64, 1024, 8192, 65536,
};
for (auto block_size : kBlockSize) {
auto alloc_free_name = fbl::StringPrintf("Arena/AllocFree/%ubytes", block_size);
perftest::RegisterTest(alloc_free_name.c_str(), ArenaAllocFreeTest, block_size);
}
static const unsigned kLargeBlockSize[] = {
4 * 1024, 8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024,
};
for (auto large_size : kLargeBlockSize) {
auto alloc_large_then_small_name =
fbl::StringPrintf("Arena/AllocLargeThenSmall/%ubytes", large_size);
perftest::RegisterTest(alloc_large_then_small_name.c_str(), ArenaAllocLargeThenSmallTest,
large_size);
}
static const unsigned kNumBlocks[] = {
1, 4, 16, 32, 1024,
};
for (auto num_blocks : kNumBlocks) {
auto contains_name = fbl::StringPrintf("Arena/Contains/%ublocks", num_blocks);
perftest::RegisterTest(contains_name.c_str(), ArenaContainsTest, num_blocks);
}
}
PERFTEST_CTOR(RegisterTests)
} // namespace