feat: initial scaffold data_table_bench (issue 0133)
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
// bench_runner — headless benchmark harness for data_table::render().
|
||||
// Issue 0133: perf gate for 10M-row refactor.
|
||||
//
|
||||
// Architecture: the Runner is driven frame-by-frame from within fn::run_app's
|
||||
// render callback. Each frame it calls data_table::render() for the current
|
||||
// scenario and measures the frame time. After duration_s seconds it moves to
|
||||
// the next scenario. After all 4 scenarios it signals completion.
|
||||
//
|
||||
// Usage in render callback:
|
||||
// static bench::Runner runner(cfg);
|
||||
// runner.tick(); // called every frame
|
||||
// if (runner.done()) { ... print + persist + close window ... }
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace bench {
|
||||
|
||||
enum class Scenario {
|
||||
LinearScroll, // advance row offset each frame
|
||||
FilterLike, // filter name CONTAINS "foo"
|
||||
SortNumeric, // sort score col descending
|
||||
ColorRule, // NumericRange color rule on value col
|
||||
};
|
||||
|
||||
inline const char* scenario_name(Scenario s) {
|
||||
switch (s) {
|
||||
case Scenario::LinearScroll: return "linear_scroll";
|
||||
case Scenario::FilterLike: return "filter_like";
|
||||
case Scenario::SortNumeric: return "sort_numeric";
|
||||
case Scenario::ColorRule: return "color_rule";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
struct ScenarioResult {
|
||||
Scenario scenario = Scenario::LinearScroll;
|
||||
double fps_p50 = 0.0;
|
||||
double fps_p1 = 0.0;
|
||||
double mem_rss_mb = 0.0;
|
||||
double cpu_pct = 0.0;
|
||||
double duration_s = 0.0;
|
||||
bool pass = false;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
long long rows = 10000000;
|
||||
int cols = 20;
|
||||
double duration_s = 30.0;
|
||||
double fps_threshold = 60.0;
|
||||
std::string db_path = "operations.db";
|
||||
std::string commit_sha;
|
||||
bool verbose = false;
|
||||
};
|
||||
|
||||
class Runner {
|
||||
public:
|
||||
explicit Runner(const Config& cfg);
|
||||
|
||||
// Called once per render frame. Internally manages scenario transitions.
|
||||
// Returns true when all scenarios are finished.
|
||||
bool tick();
|
||||
|
||||
// Returns true when all scenarios have completed.
|
||||
bool done() const { return done_; }
|
||||
|
||||
// Print JSON summary to stdout.
|
||||
void print_json() const;
|
||||
|
||||
// Persist results into bench_runs SQLite table.
|
||||
void persist(const std::string& db_path) const;
|
||||
|
||||
// Returns false if any scenario failed fps_threshold assertion.
|
||||
bool all_passed() const;
|
||||
|
||||
const std::vector<ScenarioResult>& results() const { return results_; }
|
||||
|
||||
private:
|
||||
Config cfg_;
|
||||
std::vector<ScenarioResult> results_;
|
||||
bool done_ = false;
|
||||
|
||||
// Backing storage for synthetic dataset (row-major strings).
|
||||
std::vector<std::string> backing_;
|
||||
std::vector<const char*> ptrs_;
|
||||
|
||||
// Per-scenario timing state.
|
||||
int current_scenario_ = 0;
|
||||
bool scenario_started_ = false;
|
||||
|
||||
// Frame timing for current scenario.
|
||||
using Clock = std::chrono::steady_clock;
|
||||
Clock::time_point scenario_wall_start_;
|
||||
Clock::time_point last_frame_start_;
|
||||
std::vector<double> frame_fps_;
|
||||
double user_start_ = 0.0;
|
||||
double sys_start_ = 0.0;
|
||||
|
||||
// Scenario-specific state (rebuilt each scenario).
|
||||
struct ScenarioState;
|
||||
ScenarioState* sc_state_ = nullptr;
|
||||
|
||||
int scroll_row_ = 0;
|
||||
|
||||
static constexpr Scenario kScenarios[] = {
|
||||
Scenario::LinearScroll,
|
||||
Scenario::FilterLike,
|
||||
Scenario::SortNumeric,
|
||||
Scenario::ColorRule,
|
||||
};
|
||||
static constexpr int kNumScenarios = 4;
|
||||
|
||||
void seed_dataset();
|
||||
void begin_scenario(Scenario s);
|
||||
void finish_scenario();
|
||||
void render_table_frame(Scenario s);
|
||||
};
|
||||
|
||||
// Measure RSS memory in MB (Linux: /proc/self/status).
|
||||
double measure_rss_mb();
|
||||
|
||||
// Measure CPU % from RUSAGE delta over wall time.
|
||||
double measure_cpu_pct(double wall_s, double user_s, double sys_s);
|
||||
|
||||
} // namespace bench
|
||||
Reference in New Issue
Block a user