3939
4040namespace {
4141
42- // The arena replay lives under samples/content/reader/arena/. Benchmarks
43- // run from various working dirs, so we resolve the path relative to the
44- // fixtures dir that CMake exposes via VTX_BENCH_FIXTURES_DIR.
45- std::string ArenaReplayPath () {
46- return (std::filesystem::path (VTX_BENCH_FIXTURES_DIR ).parent_path ().parent_path ()
47- / " samples " / " content " / " reader" / " arena" / " arena_from_fbs_ds.vtx" )
48- .string ();
49- }
42+ // The arena replay lives under samples/content/reader/arena/. Benchmarks
43+ // run from various working dirs, so we resolve the path relative to the
44+ // fixtures dir that CMake exposes via VTX_BENCH_FIXTURES_DIR.
45+ std::string ArenaReplayPath () {
46+ return (std::filesystem::path (VTX_BENCH_FIXTURES_DIR ).parent_path ().parent_path () / " samples " / " content " /
47+ " reader" / " arena" / " arena_from_fbs_ds.vtx" )
48+ .string ();
49+ }
5050
51- struct SilenceDebugLogsOnce {
52- SilenceDebugLogsOnce () { VTX::Logger::Instance ().SetDebugEnabled (false ); }
53- };
54- const SilenceDebugLogsOnce silence_accessor_debug_logs_once{};
55-
56- // Small bundle that holds the reader + accessor + resolved keys. Moving
57- // this construction out of the measured loop is intentional -- a real
58- // integration resolves keys once at setup, not per frame.
59- struct AccessorFixture {
60- VTX ::ReaderContext reader_result;
61- VTX ::FrameAccessor accessor;
62- VTX ::PropertyKey<VTX ::Vector> key_position;
63- VTX ::PropertyKey<float > key_health;
64- VTX ::PropertyKey<std::string> key_unique_id;
65-
66- static AccessorFixture Load (benchmark::State& state) {
67- AccessorFixture f;
68- f.reader_result = VTX::OpenReplayFile (ArenaReplayPath ());
69- if (!f.reader_result ) {
70- state.SkipWithError (" OpenReplayFile failed (run vtx_sample_generate + vtx_sample_advance_write first)" );
71- return f;
72- }
73- f. accessor = f.reader_result .reader ->CreateAccessor ();
74- f.key_position = f.accessor .Get <VTX ::Vector>(" Player" , " Position" );
75- f. key_health = f.accessor .Get <float >(" Player" , " Health" );
76- f.key_unique_id = f.accessor .Get <std::string>(" Player" , " UniqueID" );
51+ struct SilenceDebugLogsOnce {
52+ SilenceDebugLogsOnce () { VTX::Logger::Instance ().SetDebugEnabled (false ); }
53+ };
54+ const SilenceDebugLogsOnce silence_accessor_debug_logs_once {};
55+
56+ // Small bundle that holds the reader + accessor + resolved keys. Moving
57+ // this construction out of the measured loop is intentional -- a real
58+ // integration resolves keys once at setup, not per frame.
59+ struct AccessorFixture {
60+ VTX ::ReaderContext reader_result;
61+ VTX ::FrameAccessor accessor;
62+ VTX ::PropertyKey<VTX ::Vector> key_position;
63+ VTX ::PropertyKey<float > key_health;
64+ VTX ::PropertyKey<std::string> key_unique_id;
65+
66+ static AccessorFixture Load (benchmark::State& state) {
67+ AccessorFixture f;
68+ f.reader_result = VTX::OpenReplayFile (ArenaReplayPath ());
69+ if (!f.reader_result ) {
70+ state.SkipWithError (" OpenReplayFile failed (run vtx_sample_generate + vtx_sample_advance_write first)" );
71+ return f;
72+ }
73+ f. accessor = f.reader_result .reader ->CreateAccessor ();
74+ f.key_position = f.accessor .Get <VTX ::Vector>(" Player" , " Position" );
75+ f. key_health = f.accessor .Get <float >(" Player" , " Health" );
76+ f.key_unique_id = f.accessor .Get <std::string>(" Player" , " UniqueID" );
7777
78- if (!f.key_position .IsValid () || !f.key_health .IsValid () || !f.key_unique_id .IsValid ()) {
79- state.SkipWithError (" one or more Player keys did not resolve" );
78+ if (!f.key_position .IsValid () || !f.key_health .IsValid () || !f.key_unique_id .IsValid ()) {
79+ state.SkipWithError (" one or more Player keys did not resolve" );
80+ }
81+ return f;
8082 }
81- return f;
82- }
83- };
83+ };
8484
85- } // namespace
85+ } // namespace
8686
8787// Open the replay, create the accessor, resolve three keys, then linearly
8888// enumerate every frame, iterate every entity in the "entity" bucket, and
@@ -92,24 +92,27 @@ static void BM_AccessorSequentialScan(benchmark::State& state) {
9292 int32_t total_frames = 0 ;
9393 for (auto _ : state) {
9494 auto fixture = AccessorFixture::Load (state);
95- if (!fixture.reader_result ) break ;
95+ if (!fixture.reader_result )
96+ break ;
9697 auto & reader = fixture.reader_result .reader ;
9798
9899 total_frames = reader->GetTotalFrames ();
99100 double pos_accum = 0.0 ;
100- float hp_accum = 0 .0f ;
101- size_t id_count = 0 ;
101+ float hp_accum = 0 .0f ;
102+ size_t id_count = 0 ;
102103
103104 for (int32_t i = 0 ; i < total_frames; ++i) {
104105 const auto * frame = reader->GetFrameSync (i);
105- if (!frame) continue ;
106+ if (!frame)
107+ continue ;
106108 for (const auto & bucket : frame->GetBuckets ()) {
107109 for (const auto & entity : bucket.entities ) {
108- if (entity.entity_type_id != 0 ) continue ; // 0 = Player
110+ if (entity.entity_type_id != 0 )
111+ continue ; // 0 = Player
109112 VTX ::EntityView view (entity);
110113 pos_accum += view.Get (fixture.key_position ).x ;
111- hp_accum += view.Get (fixture.key_health );
112- id_count += view.Get (fixture.key_unique_id ).size ();
114+ hp_accum += view.Get (fixture.key_health );
115+ id_count += view.Get (fixture.key_unique_id ).size ();
113116 }
114117 }
115118 }
@@ -128,12 +131,15 @@ BENCHMARK(BM_AccessorSequentialScan)->Unit(benchmark::kMillisecond);
128131// the replay in memory would observe when scrubbing over the properties.
129132static void BM_AccessorHotLoopPreloaded (benchmark::State& state) {
130133 auto result = VTX::OpenReplayFile (ArenaReplayPath ());
131- if (!result) { state.SkipWithError (" OpenReplayFile failed" ); return ; }
134+ if (!result) {
135+ state.SkipWithError (" OpenReplayFile failed" );
136+ return ;
137+ }
132138 auto & reader = result.reader ;
133139
134- auto accessor = reader->CreateAccessor ();
140+ auto accessor = reader->CreateAccessor ();
135141 auto key_position = accessor.Get <VTX ::Vector>(" Player" , " Position" );
136- auto key_health = accessor.Get <float >(" Player" , " Health" );
142+ auto key_health = accessor.Get <float >(" Player" , " Health" );
137143 if (!key_position.IsValid () || !key_health.IsValid ()) {
138144 state.SkipWithError (" keys did not resolve" );
139145 return ;
@@ -161,7 +167,8 @@ static void BM_AccessorHotLoopPreloaded(benchmark::State& state) {
161167 for (const auto & frame : ram_cache) {
162168 for (const auto & bucket : frame.GetBuckets ()) {
163169 for (const auto & entity : bucket.entities ) {
164- if (entity.entity_type_id == 0 ) ++entities_per_sweep;
170+ if (entity.entity_type_id == 0 )
171+ ++entities_per_sweep;
165172 }
166173 }
167174 }
@@ -171,7 +178,8 @@ static void BM_AccessorHotLoopPreloaded(benchmark::State& state) {
171178 for (const auto & frame : ram_cache) {
172179 for (const auto & bucket : frame.GetBuckets ()) {
173180 for (const auto & entity : bucket.entities ) {
174- if (entity.entity_type_id != 0 ) continue ;
181+ if (entity.entity_type_id != 0 )
182+ continue ;
175183 VTX ::EntityView view (entity);
176184 sink += view.Get (key_position).x + view.Get (key_health);
177185 }
@@ -189,10 +197,13 @@ BENCHMARK(BM_AccessorHotLoopPreloaded)->Unit(benchmark::kMillisecond);
189197// behaviour under non-sequential access.
190198static void BM_AccessorRandomWithinBucket (benchmark::State& state) {
191199 auto result = VTX::OpenReplayFile (ArenaReplayPath ());
192- if (!result) { state.SkipWithError (" OpenReplayFile failed" ); return ; }
200+ if (!result) {
201+ state.SkipWithError (" OpenReplayFile failed" );
202+ return ;
203+ }
193204 auto & reader = result.reader ;
194205
195- auto accessor = reader->CreateAccessor ();
206+ auto accessor = reader->CreateAccessor ();
196207 auto key_position = accessor.Get <VTX ::Vector>(" Player" , " Position" );
197208 if (!key_position.IsValid ()) {
198209 state.SkipWithError (" Player::Position did not resolve" );
@@ -227,16 +238,20 @@ static void BM_AccessorRandomWithinBucket(benchmark::State& state) {
227238 std::vector<size_t > idxs;
228239 idxs.reserve (bucket.entities .size ());
229240 for (size_t i = 0 ; i < bucket.entities .size (); ++i) {
230- if (bucket.entities [i].entity_type_id == 0 ) idxs.push_back (i);
231- if (bucket.entities [i].entity_type_id == 0 ) idxs.push_back (i);
241+ if (bucket.entities [i].entity_type_id == 0 )
242+ idxs.push_back (i);
243+ if (bucket.entities [i].entity_type_id == 0 )
244+ idxs.push_back (i);
232245 }
233- if (idxs.size () < 2 ) continue ;
246+ if (idxs.size () < 2 )
247+ continue ;
234248 std::shuffle (idxs.begin (), idxs.end (), rng);
235249 prepared.push_back ({&bucket.entities , std::move (idxs)});
236250 }
237251 }
238252 int64_t ops_per_sweep = 0 ;
239- for (const auto & pb : prepared) ops_per_sweep += static_cast <int64_t >(pb.shuffled .size ());
253+ for (const auto & pb : prepared)
254+ ops_per_sweep += static_cast <int64_t >(pb.shuffled .size ());
240255
241256 double sink = 0.0 ;
242257 for (auto _ : state) {
0 commit comments