Skip to content

Commit 8f54d58

Browse files
committed
Added: Iter::view() and view(idx) benchmark
1 parent 03a4e9d commit 8f54d58

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed

src/perf/iter/src/main.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,32 @@ constexpr uint32_t EntitiesPerArchetype = 1'000;
88

99
using TBenchmarkTypes = cnt::darray<ecs::Entity>;
1010

11+
struct Position {
12+
float x, y, z;
13+
};
14+
struct Velocity {
15+
float x, y, z;
16+
};
17+
struct Rotation {
18+
float x, y, z, w;
19+
};
20+
struct Scale {
21+
float x, y, z;
22+
};
23+
struct Direction {
24+
float x, y, z;
25+
};
26+
struct Health {
27+
int value;
28+
int max;
29+
};
30+
struct IsEnemy {
31+
bool value;
32+
};
33+
struct Dummy {
34+
int value[24];
35+
};
36+
1137
auto create_archetypes(ecs::World& w, uint32_t archetypes, uint32_t maxIdsPerArchetype) {
1238
GAIA_ASSERT(archetypes > 0);
1339
GAIA_ASSERT(maxIdsPerArchetype > 0);
@@ -85,6 +111,77 @@ void bench_query_each_iter(picobench::state& state, TQuery& query) {
85111
}
86112
}
87113

114+
template <uint32_t NViews, bool ViewWithIndex>
115+
void bench_query_each_view(picobench::state& state, ecs::World& w) {
116+
/* We want to benchmark the hot-path. In real-world scenarios queries are cached so cache them now */
117+
auto q = w.query().all<Position>();
118+
if constexpr (NViews > 1)
119+
q.all<Velocity>();
120+
if constexpr (NViews > 2)
121+
q.all<Scale>();
122+
if constexpr (NViews > 3)
123+
q.all<Direction>();
124+
if constexpr (NViews > 4)
125+
q.all<Health>();
126+
127+
[[maybe_unused]] bool isEmpty = q.empty();
128+
gaia::dont_optimize(isEmpty);
129+
130+
state.stop_timer();
131+
for (auto _: state) {
132+
(void)_;
133+
134+
state.stop_timer();
135+
q.each([&](ecs::Iter& it) {
136+
GAIA_EACH(it) {
137+
state.start_timer();
138+
139+
if constexpr (ViewWithIndex) {
140+
auto v1 = it.template view<Position>(0);
141+
gaia::dont_optimize(v1);
142+
if constexpr (NViews > 2) {
143+
auto v2 = it.template view<Velocity>(1);
144+
gaia::dont_optimize(v2);
145+
}
146+
if constexpr (NViews > 2) {
147+
auto v3 = it.template view<Scale>(2);
148+
gaia::dont_optimize(v3);
149+
}
150+
if constexpr (NViews > 3) {
151+
auto v4 = it.template view<Direction>(3);
152+
gaia::dont_optimize(v4);
153+
}
154+
if constexpr (NViews > 4) {
155+
auto v5 = it.template view<Health>(4);
156+
gaia::dont_optimize(v5);
157+
}
158+
} else {
159+
auto v1 = it.template view<Position>();
160+
gaia::dont_optimize(v1);
161+
if constexpr (NViews > 2) {
162+
auto v2 = it.template view<Velocity>();
163+
gaia::dont_optimize(v2);
164+
}
165+
if constexpr (NViews > 2) {
166+
auto v3 = it.template view<Scale>();
167+
gaia::dont_optimize(v3);
168+
}
169+
if constexpr (NViews > 3) {
170+
auto v4 = it.template view<Direction>();
171+
gaia::dont_optimize(v4);
172+
}
173+
if constexpr (NViews > 4) {
174+
auto v5 = it.template view<Health>();
175+
gaia::dont_optimize(v5);
176+
}
177+
}
178+
179+
state.stop_timer();
180+
}
181+
});
182+
}
183+
}
184+
88185
template <bool UseCachedQuery, uint32_t QueryComponents>
89186
void BM_BuildQuery(picobench::state& state) {
90187
ecs::World w;
@@ -150,6 +247,88 @@ void BM_Each_Iter(picobench::state& state, uint32_t ArchetypeCount, uint32_t Max
150247
bench_query_each_iter<IterKind>(state, query);
151248
}
152249

250+
template <uint32_t NViews, bool ViewWithIndex>
251+
void BM_Each_View(picobench::state& state) {
252+
ecs::World w;
253+
254+
// Create some archetypes for a good measure
255+
create_archetypes(w, 1000, 10);
256+
257+
// Register our components. The order is random so it does not match
258+
// the order in queries.
259+
{
260+
(void)w.add<Scale>();
261+
(void)w.add<Position>();
262+
(void)w.add<Direction>();
263+
(void)w.add<Health>();
264+
(void)w.add<IsEnemy>();
265+
(void)w.add<Velocity>();
266+
(void)w.add<Rotation>();
267+
}
268+
269+
// Create our native component archetypes
270+
constexpr uint32_t NEntities = 1000;
271+
{
272+
auto e = w.add();
273+
w.build(e) //
274+
.add<Position>()
275+
.add<Velocity>();
276+
w.copy_n(e, NEntities - 1);
277+
}
278+
{
279+
auto e = w.add();
280+
w.build(e) //
281+
.add<Position>()
282+
.add<Velocity>()
283+
.add<Rotation>();
284+
w.copy_n(e, NEntities - 1);
285+
}
286+
{
287+
auto e = w.add();
288+
w.build(e) //
289+
.add<Position>()
290+
.add<Velocity>()
291+
.add<Rotation>()
292+
.add<Scale>();
293+
w.copy_n(e, NEntities - 1);
294+
}
295+
{
296+
auto e = w.add();
297+
w.build(e) //
298+
.add<Position>()
299+
.add<Velocity>()
300+
.add<Rotation>()
301+
.add<Scale>()
302+
.add<Direction>();
303+
w.copy_n(e, NEntities - 1);
304+
}
305+
{
306+
auto e = w.add();
307+
w.build(e) //
308+
.add<Position>()
309+
.add<Velocity>()
310+
.add<Rotation>()
311+
.add<Scale>()
312+
.add<Direction>()
313+
.add<Health>();
314+
w.copy_n(e, NEntities - 1);
315+
}
316+
{
317+
auto e = w.add();
318+
w.build(e) //
319+
.add<Position>()
320+
.add<Velocity>()
321+
.add<Rotation>()
322+
.add<Scale>()
323+
.add<Direction>()
324+
.add<Health>()
325+
.add<IsEnemy>();
326+
w.copy_n(e, NEntities - 1);
327+
}
328+
329+
bench_query_each_view<NViews, ViewWithIndex>(state, w);
330+
}
331+
153332
#define DEFINE_EACH_ITER(IterKind, ArchetypeCount, MaxIdsPerArchetype, QueryComponents) \
154333
void BM_Each_##IterKind##_##ArchetypeCount##_##QueryComponents(picobench::state& state) { \
155334
BM_Each_Iter<true, QueryComponents, ecs::IterKind>(state, ArchetypeCount, MaxIdsPerArchetype); \
@@ -159,6 +338,11 @@ void BM_Each_Iter(picobench::state& state, uint32_t ArchetypeCount, uint32_t Max
159338
BM_Each_Iter<false, QueryComponents, ecs::IterKind>(state, ArchetypeCount, MaxIdsPerArchetype); \
160339
}
161340

341+
#define DEFINE_EACH_VIEW(NViews, ViewWithIndex) \
342+
void BM_Each_View_##NViews##_##ViewWithIndex(picobench::state& state) { \
343+
BM_Each_View<NViews, ViewWithIndex>(state); \
344+
}
345+
162346
DEFINE_EACH_ITER(IterAll, 1, 1, 1)
163347
DEFINE_EACH_ITER(Iter, 1, 1, 1)
164348
DEFINE_EACH_U_ITER(Iter, 1, 1, 1)
@@ -179,6 +363,17 @@ DEFINE_EACH_U_ITER(Iter, 1000, 10, 3);
179363
DEFINE_EACH_U_ITER(Iter, 1000, 10, 5);
180364
DEFINE_EACH_U_ITER(Iter, 1000, 10, 7);
181365

366+
DEFINE_EACH_VIEW(1, false);
367+
DEFINE_EACH_VIEW(1, true);
368+
DEFINE_EACH_VIEW(2, false);
369+
DEFINE_EACH_VIEW(2, true);
370+
DEFINE_EACH_VIEW(3, false);
371+
DEFINE_EACH_VIEW(3, true);
372+
DEFINE_EACH_VIEW(4, false);
373+
DEFINE_EACH_VIEW(4, true);
374+
DEFINE_EACH_VIEW(5, false);
375+
DEFINE_EACH_VIEW(5, true);
376+
182377
#define PICO_SETTINGS() iterations({8192}).samples(3)
183378
#define PICO_SETTINGS_1() iterations({8192}).samples(1)
184379
#define PICO_SETTINGS_SANI() iterations({8}).samples(1)
@@ -260,6 +455,18 @@ int main(int argc, char* argv[]) {
260455
PICOBENCH_REG(BM_BuildQuery_U_5).PICO_SETTINGS().label("(u) 5 comps"); // uncached
261456
PICOBENCH_REG(BM_BuildQuery_7).PICO_SETTINGS().label("7 comps");
262457
PICOBENCH_REG(BM_BuildQuery_U_7).PICO_SETTINGS().label("(u) 7 comps"); // uncached
458+
459+
PICOBENCH_SUITE_REG("Iter view");
460+
PICOBENCH_REG(BM_Each_View_1_false).PICO_SETTINGS().label("view 1 comp");
461+
PICOBENCH_REG(BM_Each_View_1_true).PICO_SETTINGS().label("view 1 comp, idx");
462+
PICOBENCH_REG(BM_Each_View_2_false).PICO_SETTINGS().label("view 2 comp");
463+
PICOBENCH_REG(BM_Each_View_2_true).PICO_SETTINGS().label("view 2 comp, idx");
464+
PICOBENCH_REG(BM_Each_View_3_false).PICO_SETTINGS().label("view 3 comp");
465+
PICOBENCH_REG(BM_Each_View_3_true).PICO_SETTINGS().label("view 3 comp, idx");
466+
PICOBENCH_REG(BM_Each_View_4_false).PICO_SETTINGS().label("view 4 comp");
467+
PICOBENCH_REG(BM_Each_View_4_true).PICO_SETTINGS().label("view 4 comp, idx");
468+
PICOBENCH_REG(BM_Each_View_5_false).PICO_SETTINGS().label("view 5 comp");
469+
PICOBENCH_REG(BM_Each_View_5_true).PICO_SETTINGS().label("view 5 comp, idx");
263470
}
264471
}
265472

0 commit comments

Comments
 (0)