Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions include/benchmark/benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ namespace benchmark {
class BenchmarkReporter;
class State;

using IterationCount = int64_t;

// Define alias of Setup/Teardown callback function type
using callback_function = std::function<void(const benchmark::State&)>;

Expand Down Expand Up @@ -394,7 +396,8 @@ class MemoryManager {
: num_allocs(0),
max_bytes_used(0),
total_allocated_bytes(TombstoneValue),
net_heap_growth(TombstoneValue) {}
net_heap_growth(TombstoneValue),
memory_iterations(0) {}

// The number of allocations made in total between Start and Stop.
int64_t num_allocs;
Expand All @@ -410,6 +413,8 @@ class MemoryManager {
// ie., total_allocated_bytes - total_deallocated_bytes.
// Init'ed to TombstoneValue if metric not available.
int64_t net_heap_growth;

IterationCount memory_iterations;
};

virtual ~MemoryManager() {}
Expand Down Expand Up @@ -659,8 +664,6 @@ enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };

typedef int64_t ComplexityN;

typedef int64_t IterationCount;

enum StatisticUnit { kTime, kPercentage };

// BigOFunc is passed to a benchmark in order to specify the asymptotic
Expand Down Expand Up @@ -1721,7 +1724,6 @@ class BENCHMARK_EXPORT BenchmarkReporter {
complexity_n(0),
report_big_o(false),
report_rms(false),
memory_result(NULL),
allocs_per_iter(0.0) {}

std::string benchmark_name() const;
Expand Down Expand Up @@ -1777,7 +1779,7 @@ class BENCHMARK_EXPORT BenchmarkReporter {
UserCounters counters;

// Memory metrics.
const MemoryManager::Result* memory_result;
MemoryManager::Result memory_result;
double allocs_per_iter;
};

Expand Down
18 changes: 7 additions & 11 deletions src/benchmark_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ BenchmarkReporter::Run CreateRunReport(
const benchmark::internal::BenchmarkInstance& b,
const internal::ThreadManager::Result& results,
IterationCount memory_iterations,
const MemoryManager::Result* memory_result, double seconds,
const MemoryManager::Result& memory_result, double seconds,
int64_t repetition_index, int64_t repeats) {
// Create report about this benchmark run.
BenchmarkReporter::Run report;
Expand Down Expand Up @@ -114,11 +114,10 @@ BenchmarkReporter::Run CreateRunReport(
report.counters = results.counters;

if (memory_iterations > 0) {
assert(memory_result != nullptr);
report.memory_result = memory_result;
report.allocs_per_iter =
memory_iterations != 0
? static_cast<double>(memory_result->num_allocs) /
? static_cast<double>(memory_result.num_allocs) /
static_cast<double>(memory_iterations)
: 0;
}
Expand Down Expand Up @@ -426,13 +425,8 @@ void BenchmarkRunner::RunWarmUp() {
}
}

MemoryManager::Result* BenchmarkRunner::RunMemoryManager(
MemoryManager::Result BenchmarkRunner::RunMemoryManager(
IterationCount memory_iterations) {
// TODO(vyng): Consider making BenchmarkReporter::Run::memory_result an
// optional so we don't have to own the Result here.
// Can't do it now due to cxx03.
memory_results.push_back(MemoryManager::Result());
MemoryManager::Result* memory_result = &memory_results.back();
memory_manager->Start();
std::unique_ptr<internal::ThreadManager> manager;
manager.reset(new internal::ThreadManager(1));
Expand All @@ -443,7 +437,9 @@ MemoryManager::Result* BenchmarkRunner::RunMemoryManager(
manager->WaitForAllThreads();
manager.reset();
b.Teardown();
memory_manager->Stop(*memory_result);
MemoryManager::Result memory_result;
memory_manager->Stop(memory_result);
memory_result.memory_iterations = memory_iterations;
return memory_result;
}

Expand Down Expand Up @@ -508,7 +504,7 @@ void BenchmarkRunner::DoOneRepetition() {
}

// Produce memory measurements if requested.
MemoryManager::Result* memory_result = nullptr;
MemoryManager::Result memory_result;
IterationCount memory_iterations = 0;
if (memory_manager != nullptr) {
// Only run a few iterations to reduce the impact of one-time
Expand Down
4 changes: 1 addition & 3 deletions src/benchmark_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ class BenchmarkRunner {

std::vector<std::thread> pool;

std::vector<MemoryManager::Result> memory_results;

IterationCount iters; // preserved between repetitions!
// So only the first repetition has to find/calculate it,
// the other repetitions will just use that precomputed iteration count.
Expand All @@ -106,7 +104,7 @@ class BenchmarkRunner {
};
IterationResults DoNIterations();

MemoryManager::Result* RunMemoryManager(IterationCount memory_iterations);
MemoryManager::Result RunMemoryManager(IterationCount memory_iterations);

void RunProfilerManager(IterationCount profile_iterations);

Expand Down
4 changes: 2 additions & 2 deletions src/json_reporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ void JSONReporter::PrintRunData(Run const& run) {
out << ",\n" << indent << FormatKV(c.first, c.second);
}

if (run.memory_result != nullptr) {
const MemoryManager::Result memory_result = *run.memory_result;
if (run.memory_result.memory_iterations > 0) {
const auto& memory_result = run.memory_result;
out << ",\n" << indent << FormatKV("allocs_per_iter", run.allocs_per_iter);
out << ",\n"
<< indent << FormatKV("max_bytes_used", memory_result.max_bytes_used);
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ if (BENCHMARK_ENABLE_GTEST_TESTS)
add_gtest(min_time_parse_gtest)
add_gtest(profiler_manager_gtest)
add_gtest(benchmark_setup_teardown_cb_types_gtest)
add_gtest(memory_results_gtest)
endif(BENCHMARK_ENABLE_GTEST_TESTS)

###############################################################################
Expand Down
101 changes: 101 additions & 0 deletions test/memory_results_gtest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <vector>

#include "../src/benchmark_runner.h"
#include "benchmark/benchmark.h"
#include "gtest/gtest.h"

#define N_REPETITIONS 100
#define N_ITERATIONS 1

using benchmark::ClearRegisteredBenchmarks;
using benchmark::ConsoleReporter;
using benchmark::MemoryManager;
using benchmark::RegisterBenchmark;
using benchmark::RunSpecifiedBenchmarks;
using benchmark::State;
using benchmark::internal::Benchmark;

namespace counts {
int num_allocs = 0;
int max_bytes_used = 0;
int total_allocated_bytes = 0;
int net_heap_growth = 0;
void reset() {
num_allocs = 0;
max_bytes_used = 0;
total_allocated_bytes = 0;
net_heap_growth = 0;
}
} // namespace counts

class TestMemoryManager : public MemoryManager {
void Start() override {}
void Stop(Result& result) override {
result.num_allocs = counts::num_allocs;
result.net_heap_growth = counts::net_heap_growth;
result.max_bytes_used = counts::max_bytes_used;
result.total_allocated_bytes = counts::total_allocated_bytes;

counts::num_allocs += 1;
counts::max_bytes_used += 2;
counts::net_heap_growth += 4;
counts::total_allocated_bytes += 10;
}
};

class TestReporter : public ConsoleReporter {
public:
TestReporter() = default;
virtual ~TestReporter() = default;

bool ReportContext(const Context& /*unused*/) override { return true; }

void PrintHeader(const Run&) override {}
void PrintRunData(const Run& run) override {
if (run.repetition_index == -1) return;
if (!run.memory_result.memory_iterations) return;

store.push_back(run.memory_result);
}

std::vector<MemoryManager::Result> store;
};

class MemoryResultsTest : public testing::Test {
public:
Benchmark* bm;
TestReporter reporter;

void SetUp() override {
bm = RegisterBenchmark("BM", [](State& st) {
for (auto _ : st) {
}
});
bm->Repetitions(N_REPETITIONS);
bm->Iterations(N_ITERATIONS);
}
void TearDown() override { ClearRegisteredBenchmarks(); }
};

TEST_F(MemoryResultsTest, NoMMTest) {
RunSpecifiedBenchmarks(&reporter);
EXPECT_EQ(reporter.store.size(), 0);
}

TEST_F(MemoryResultsTest, ResultsTest) {
counts::reset();
MemoryManager* mm = new TestMemoryManager;
RegisterMemoryManager(mm);

RunSpecifiedBenchmarks(&reporter);
EXPECT_EQ(reporter.store.size(), N_REPETITIONS);

for (size_t i = 0; i < reporter.store.size(); i++) {
EXPECT_EQ(reporter.store[i].num_allocs, i);
EXPECT_EQ(reporter.store[i].max_bytes_used, i * 2);
EXPECT_EQ(reporter.store[i].net_heap_growth, i * 4);
EXPECT_EQ(reporter.store[i].total_allocated_bytes, i * 10);
}

delete mm;
}
Loading