Add complete benchmark infrastructure with 4 benchmark categories: **Benchmark Helpers (00_helpers.md)** - BenchmarkTimer.h: High-resolution timing with std::chrono - BenchmarkStats.h: Statistical analysis (mean, median, p95, p99, stddev) - BenchmarkReporter.h: Professional formatted output - benchmark_helpers_demo.cpp: Validation suite **TopicTree Routing (01_topictree.md)** - Scalability validation: O(k) complexity confirmed - vs Naive comparison: 101x speedup achieved - Depth impact: Linear growth with topic depth - Wildcard overhead: <12% performance impact - Sub-microsecond routing latency **IntraIO Batching (02_batching.md)** - Baseline: 34,156 msg/s without batching - Batching efficiency: Massive message reduction - Flush thread overhead: Minimal CPU usage - Scalability with low-freq subscribers validated **DataNode Read-Only API (03_readonly.md)** - Zero-copy speedup: 2x faster than getChild() - Concurrent reads: 23.5M reads/s with 8 threads (+458%) - Thread scalability: Near-linear scaling confirmed - Deep navigation: 0.005µs per level **End-to-End Real World (04_e2e.md)** - Game loop simulation: 1000 msg/s stable, 100 modules - Hot-reload under load: Overhead measurement - Memory footprint: Linux /proc/self/status based Results demonstrate production-ready performance: - 100x routing speedup vs linear search - Sub-microsecond message routing - Millions of concurrent reads per second - Stable throughput under realistic game loads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
139 lines
3.9 KiB
C++
139 lines
3.9 KiB
C++
#pragma once
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
namespace GroveEngine {
|
|
namespace Benchmark {
|
|
|
|
/**
|
|
* Formatted reporter for benchmark results.
|
|
* Provides consistent and readable output for benchmark data.
|
|
*/
|
|
class BenchmarkReporter {
|
|
public:
|
|
BenchmarkReporter(std::ostream& out = std::cout) : out(out) {}
|
|
|
|
/**
|
|
* Print a header for a benchmark section.
|
|
*/
|
|
void printHeader(const std::string& name) {
|
|
out << "\n";
|
|
printSeparator('=');
|
|
out << "BENCHMARK: " << name << "\n";
|
|
printSeparator('=');
|
|
}
|
|
|
|
/**
|
|
* Print a single result metric.
|
|
*/
|
|
void printResult(const std::string& metric, double value, const std::string& unit) {
|
|
out << std::left << std::setw(20) << metric << ": "
|
|
<< std::right << std::setw(10) << std::fixed << std::setprecision(2)
|
|
<< value << " " << unit << "\n";
|
|
}
|
|
|
|
/**
|
|
* Print a comparison between two values.
|
|
*/
|
|
void printComparison(const std::string& name1, double val1,
|
|
const std::string& name2, double val2) {
|
|
double percentChange = ((val2 - val1) / val1) * 100.0;
|
|
std::string sign = percentChange >= 0 ? "+" : "";
|
|
|
|
out << std::left << std::setw(20) << name1 << ": "
|
|
<< std::right << std::setw(10) << std::fixed << std::setprecision(2)
|
|
<< val1 << " µs\n";
|
|
|
|
out << std::left << std::setw(20) << name2 << ": "
|
|
<< std::right << std::setw(10) << std::fixed << std::setprecision(2)
|
|
<< val2 << " µs (" << sign << std::fixed << std::setprecision(1)
|
|
<< percentChange << "%)\n";
|
|
}
|
|
|
|
/**
|
|
* Print a subsection separator.
|
|
*/
|
|
void printSubseparator() {
|
|
printSeparator('-');
|
|
}
|
|
|
|
/**
|
|
* Print a summary footer.
|
|
*/
|
|
void printSummary(const std::string& summary) {
|
|
printSeparator('-');
|
|
out << "✅ RESULT: " << summary << "\n";
|
|
printSeparator('=');
|
|
out << std::endl;
|
|
}
|
|
|
|
/**
|
|
* Print detailed statistics.
|
|
*/
|
|
void printStats(const std::string& label, double mean, double median,
|
|
double p95, double p99, double min, double max,
|
|
double stddev, const std::string& unit) {
|
|
out << "\n" << label << " Statistics:\n";
|
|
printSubseparator();
|
|
printResult("Mean", mean, unit);
|
|
printResult("Median", median, unit);
|
|
printResult("P95", p95, unit);
|
|
printResult("P99", p99, unit);
|
|
printResult("Min", min, unit);
|
|
printResult("Max", max, unit);
|
|
printResult("Stddev", stddev, unit);
|
|
}
|
|
|
|
/**
|
|
* Print a simple message.
|
|
*/
|
|
void printMessage(const std::string& message) {
|
|
out << message << "\n";
|
|
}
|
|
|
|
/**
|
|
* Print a table header.
|
|
*/
|
|
void printTableHeader(const std::string& col1, const std::string& col2,
|
|
const std::string& col3 = "") {
|
|
out << "\n";
|
|
out << std::left << std::setw(25) << col1
|
|
<< std::right << std::setw(15) << col2;
|
|
if (!col3.empty()) {
|
|
out << std::right << std::setw(15) << col3;
|
|
}
|
|
out << "\n";
|
|
printSeparator('-');
|
|
}
|
|
|
|
/**
|
|
* Print a table row.
|
|
*/
|
|
void printTableRow(const std::string& col1, double col2,
|
|
const std::string& unit, double col3 = -1.0) {
|
|
out << std::left << std::setw(25) << col1
|
|
<< std::right << std::setw(12) << std::fixed << std::setprecision(2)
|
|
<< col2 << " " << std::setw(2) << unit;
|
|
|
|
if (col3 >= 0.0) {
|
|
std::string sign = col3 >= 0 ? "+" : "";
|
|
out << std::right << std::setw(12) << sign << std::fixed
|
|
<< std::setprecision(1) << col3 << "%";
|
|
}
|
|
out << "\n";
|
|
}
|
|
|
|
private:
|
|
std::ostream& out;
|
|
|
|
void printSeparator(char c = '=') {
|
|
out << std::string(60, c) << "\n";
|
|
}
|
|
};
|
|
|
|
} // namespace Benchmark
|
|
} // namespace GroveEngine
|