Add benchmarks
This commit is contained in:
		
							parent
							
								
									72f635400a
								
							
						
					
					
						commit
						acc03a75aa
					
				
					 1 changed files with 437 additions and 31 deletions
				
			
		
							
								
								
									
										458
									
								
								tests/zecsy.cpp
									
									
									
									
									
								
							
							
						
						
									
										458
									
								
								tests/zecsy.cpp
									
									
									
									
									
								
							|  | @ -7,7 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| using namespace zecsy; | using namespace zecsy; | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Create a single entity and verify its existence") | TEST_CASE("Create a single entity and verify its existence", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -16,7 +16,8 @@ TEST_CASE("Create a single entity and verify its existence") | ||||||
|     REQUIRE(w.is_alive(e)); |     REQUIRE(w.is_alive(e)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Destroy an entity and ensure it no longer exists in the world") | TEST_CASE("Destroy an entity and ensure it no longer exists in the world", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -26,7 +27,7 @@ TEST_CASE("Destroy an entity and ensure it no longer exists in the world") | ||||||
|     REQUIRE_FALSE(w.is_alive(e)); |     REQUIRE_FALSE(w.is_alive(e)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Entity #0 should be reserved and never used") | TEST_CASE("Entity #0 should be reserved and never used", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -40,7 +41,8 @@ struct ChoosenOne | ||||||
| { | { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Entity shouldn't have a component that wasn't attached to it") | TEST_CASE("Entity shouldn't have a component that wasn't attached to it", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -49,7 +51,7 @@ TEST_CASE("Entity shouldn't have a component that wasn't attached to it") | ||||||
|     REQUIRE_FALSE(w.has<ChoosenOne>(e)); |     REQUIRE_FALSE(w.has<ChoosenOne>(e)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Attempt of getting non-owned component should throw") | TEST_CASE("Attempt of getting non-owned component should throw", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +61,8 @@ TEST_CASE("Attempt of getting non-owned component should throw") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Attach a simple component to an entity and verify it is correctly " | TEST_CASE("Attach a simple component to an entity and verify it is correctly " | ||||||
|           "associated") |           "associated", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -80,7 +83,8 @@ struct Comp | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Retrieve a component from an entity and verify its data matches " | TEST_CASE("Retrieve a component from an entity and verify its data matches " | ||||||
|           "what was set") |           "what was set", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -95,7 +99,8 @@ TEST_CASE("Retrieve a component from an entity and verify its data matches " | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE( | TEST_CASE( | ||||||
|     "Remove a component from an entity and verify it is no longer attached") |     "Remove a component from an entity and verify it is no longer attached", | ||||||
|  |     "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -111,7 +116,7 @@ TEST_CASE( | ||||||
|     REQUIRE_FALSE(w.has<ChoosenOne>(e)); |     REQUIRE_FALSE(w.has<ChoosenOne>(e)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Addresses of removed components should be reused") | TEST_CASE("Addresses of removed components should be reused", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     std::vector<entity_id> entities; |     std::vector<entity_id> entities; | ||||||
|  | @ -156,7 +161,8 @@ TEST_CASE("Addresses of removed components should be reused") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Attach multiple components to an entity and verify all are " | TEST_CASE("Attach multiple components to an entity and verify all are " | ||||||
|           "correctly stored and retrievable") |           "correctly stored and retrievable", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
| 
 | 
 | ||||||
|  | @ -173,7 +179,8 @@ TEST_CASE("Attach multiple components to an entity and verify all are " | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Create a simple system that processes entities with a specific " | TEST_CASE("Create a simple system that processes entities with a specific " | ||||||
|           "component and verify it executes correctly") |           "component and verify it executes correctly", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     struct Component |     struct Component | ||||||
|     { |     { | ||||||
|  | @ -200,7 +207,8 @@ TEST_CASE("Create a simple system that processes entities with a specific " | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Test a systems ability to query and process only entities with a " | TEST_CASE("Test a systems ability to query and process only entities with a " | ||||||
|           "specific combination of components") |           "specific combination of components", | ||||||
|  |           "[test]") | ||||||
| { | { | ||||||
|     struct C0 |     struct C0 | ||||||
|     { |     { | ||||||
|  | @ -226,7 +234,8 @@ TEST_CASE("Test a systems ability to query and process only entities with a " | ||||||
|     REQUIRE(w.get<C0>(e0).value == 0); |     REQUIRE(w.get<C0>(e0).value == 0); | ||||||
|     REQUIRE(w.get<C1>(e0).value == 10); |     REQUIRE(w.get<C1>(e0).value == 10); | ||||||
| 
 | 
 | ||||||
|     w.query<C0, C1>([e0](entity_id e, C0& c0, C1& c1) |     w.query<C0, C1>( | ||||||
|  |         [e0](entity_id e, C0& c0, C1& c1) | ||||||
|         { |         { | ||||||
|             REQUIRE(e == e0); |             REQUIRE(e == e0); | ||||||
|             c0.value++; |             c0.value++; | ||||||
|  | @ -243,7 +252,7 @@ TEST_CASE("Test a systems ability to query and process only entities with a " | ||||||
|     REQUIRE_FALSE(w.has<C0>(e2)); |     REQUIRE_FALSE(w.has<C0>(e2)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems execute at correct frequencies") | TEST_CASE("Systems execute at correct frequencies", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -268,7 +277,7 @@ TEST_CASE("Systems execute at correct frequencies") | ||||||
|     REQUIRE(slow_count == 2);   // 1 Hz system should execute 1 time
 |     REQUIRE(slow_count == 2);   // 1 Hz system should execute 1 time
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle zero-frequency gracefully") | TEST_CASE("Systems handle zero-frequency gracefully", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -288,7 +297,7 @@ TEST_CASE("Systems handle zero-frequency gracefully") | ||||||
|     REQUIRE(zero_count == 0); |     REQUIRE(zero_count == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle varying update rates") | TEST_CASE("Systems handle varying update rates", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -308,7 +317,7 @@ TEST_CASE("Systems handle varying update rates") | ||||||
|     REQUIRE(varying_count == 10); |     REQUIRE(varying_count == 10); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle large time steps") | TEST_CASE("Systems handle large time steps", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -325,7 +334,7 @@ TEST_CASE("Systems handle large time steps") | ||||||
|     REQUIRE(large_step_count == 2); |     REQUIRE(large_step_count == 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle multiple frequencies") | TEST_CASE("Systems handle multiple frequencies", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -351,7 +360,7 @@ TEST_CASE("Systems handle multiple frequencies") | ||||||
|     REQUIRE(slow_count == 1);    // 1 Hz system
 |     REQUIRE(slow_count == 1);    // 1 Hz system
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle fractional frequencies") | TEST_CASE("Systems handle fractional frequencies", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -372,7 +381,7 @@ TEST_CASE("Systems handle fractional frequencies") | ||||||
|     REQUIRE(fractional_count == 2); |     REQUIRE(fractional_count == 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle zero delta time") | TEST_CASE("Systems handle zero delta time", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -389,7 +398,7 @@ TEST_CASE("Systems handle zero delta time") | ||||||
|     REQUIRE(zero_dt_count == 0); |     REQUIRE(zero_dt_count == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Systems handle negative delta time") | TEST_CASE("Systems handle negative delta time", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     system_scheduler scheduler; |     system_scheduler scheduler; | ||||||
|  | @ -410,7 +419,7 @@ TEST_CASE("Systems handle negative delta time") | ||||||
|     REQUIRE(count == 2); |     REQUIRE(count == 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Entity count tracking") | TEST_CASE("Entity count tracking", "[test]") | ||||||
| { | { | ||||||
|     world w; |     world w; | ||||||
|     REQUIRE(w.entity_count() == 0); |     REQUIRE(w.entity_count() == 0); | ||||||
|  | @ -423,7 +432,7 @@ TEST_CASE("Entity count tracking") | ||||||
|     REQUIRE(w.entity_count() == 1); |     REQUIRE(w.entity_count() == 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Component counting mechanisms") | TEST_CASE("Component counting mechanisms", "[test]") | ||||||
| { | { | ||||||
|     struct Health |     struct Health | ||||||
|     { |     { | ||||||
|  | @ -454,7 +463,7 @@ TEST_CASE("Component counting mechanisms") | ||||||
|     REQUIRE(w.total_component_count() == 1); |     REQUIRE(w.total_component_count() == 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Archetype signature management") | TEST_CASE("Archetype signature management", "[test]") | ||||||
| { | { | ||||||
|     struct A |     struct A | ||||||
|     { |     { | ||||||
|  | @ -509,7 +518,7 @@ TEST_CASE("Archetype signature management") | ||||||
|     REQUIRE(w.archetype_count() == 0); |     REQUIRE(w.archetype_count() == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Component distribution across archetypes") | TEST_CASE("Component distribution across archetypes", "[test]") | ||||||
| { | { | ||||||
|     struct A |     struct A | ||||||
|     { |     { | ||||||
|  | @ -547,7 +556,7 @@ TEST_CASE("Component distribution across archetypes") | ||||||
|     REQUIRE(w.archetype_count() == 3); //<A>, <A, B>, <B>
 |     REQUIRE(w.archetype_count() == 3); //<A>, <A, B>, <B>
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Entity inspection") | TEST_CASE("Entity inspection", "[test]") | ||||||
| { | { | ||||||
|     struct Transform |     struct Transform | ||||||
|     { |     { | ||||||
|  | @ -572,3 +581,400 @@ TEST_CASE("Entity inspection") | ||||||
|     w.remove<Transform>(e); |     w.remove<Transform>(e); | ||||||
|     REQUIRE(w.components_in_entity(e) == 1); |     REQUIRE(w.components_in_entity(e) == 1); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | namespace | ||||||
|  | { | ||||||
|  |     // Benchmark components
 | ||||||
|  |     struct Position | ||||||
|  |     { | ||||||
|  |         float x, y; | ||||||
|  |     }; | ||||||
|  |     struct Velocity | ||||||
|  |     { | ||||||
|  |         float dx, dy; | ||||||
|  |     }; | ||||||
|  |     struct Health | ||||||
|  |     { | ||||||
|  |         int value; | ||||||
|  |     }; | ||||||
|  |     struct BigData | ||||||
|  |     { | ||||||
|  |         char buffer[4096]; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // Benchmark entity counts
 | ||||||
|  |     constexpr int SMALL = 1'000; | ||||||
|  |     constexpr int MEDIUM = 5'000; | ||||||
|  |     constexpr int LARGE = 10'000; | ||||||
|  | } // namespace
 | ||||||
|  | 
 | ||||||
|  | TEST_CASE("Core operations benchmarks", "[benchmark]") | ||||||
|  | { | ||||||
|  |     BENCHMARK_ADVANCED("Create entities [1000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < SMALL; ++i) | ||||||
|  |                 { | ||||||
|  |                     w.make_entity(); | ||||||
|  |                 } | ||||||
|  |                 return w.entity_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Create entities [5000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |                 { | ||||||
|  |                     w.make_entity(); | ||||||
|  |                 } | ||||||
|  |                 return w.entity_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Create entities [10000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < LARGE; ++i) | ||||||
|  |                 { | ||||||
|  |                     w.make_entity(); | ||||||
|  |                 } | ||||||
|  |                 return w.entity_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Create entities with components [1000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < SMALL; ++i) | ||||||
|  |                 { | ||||||
|  |                     auto e = w.make_entity(); | ||||||
|  |                     w.set<Position>(e, {1.0f, 2.0f}); | ||||||
|  |                     w.set<Velocity>(e, {3.0f, 4.0f}); | ||||||
|  |                 } | ||||||
|  |                 return w.total_component_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Create entities with components [5000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |                 { | ||||||
|  |                     auto e = w.make_entity(); | ||||||
|  |                     w.set<Position>(e, {1.0f, 2.0f}); | ||||||
|  |                     w.set<Velocity>(e, {3.0f, 4.0f}); | ||||||
|  |                 } | ||||||
|  |                 return w.total_component_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Create entities with components [10000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < LARGE; ++i) | ||||||
|  |                 { | ||||||
|  |                     auto e = w.make_entity(); | ||||||
|  |                     w.set<Position>(e, {1.0f, 2.0f}); | ||||||
|  |                     w.set<Velocity>(e, {3.0f, 4.0f}); | ||||||
|  |                 } | ||||||
|  |                 return w.total_component_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST_CASE("Component operations benchmarks", "[benchmark]") | ||||||
|  | { | ||||||
|  |     BENCHMARK_ADVANCED("Add component to existing entities [1000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < SMALL; ++i) | ||||||
|  |         { | ||||||
|  |             entities.push_back(w.make_entity()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.set<Health>(e, {100}); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Add component to existing entities [5000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |         { | ||||||
|  |             entities.push_back(w.make_entity()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.set<Health>(e, {100}); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Add component to existing entities [10000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < LARGE; ++i) | ||||||
|  |         { | ||||||
|  |             entities.push_back(w.make_entity()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.set<Health>(e, {100}); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Remove component from entities [1000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < SMALL; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Health>(e, {100}); | ||||||
|  |             entities.push_back(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.remove<Health>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Remove component from entities [5000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Health>(e, {100}); | ||||||
|  |             entities.push_back(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.remove<Health>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Remove component from entities [10000]")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < LARGE; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Health>(e, {100}); | ||||||
|  |             entities.push_back(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.remove<Health>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<Health>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST_CASE("Query performance benchmarks", "[benchmark]") | ||||||
|  | { | ||||||
|  |     BENCHMARK_ADVANCED("Dense query (90% match)")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         for(int i = 0; i < LARGE; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Position>(e); | ||||||
|  |             if(i % 10 != 0) | ||||||
|  |                 w.set<Velocity>(e); // 90% match
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 int count = 0; | ||||||
|  |                 w.query<Position, Velocity>([&](auto...) { count++; }); | ||||||
|  |                 return count; | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Sparse query (10% match)")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         for(int i = 0; i < LARGE; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Position>(e); | ||||||
|  |             if(i % 10 == 0) | ||||||
|  |                 w.set<Velocity>(e); // 10% match
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 int count = 0; | ||||||
|  |                 w.query<Position, Velocity>([&](auto...) { count++; }); | ||||||
|  |                 return count; | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST_CASE("Memory intensive benchmarks", "[benchmark]") | ||||||
|  | { | ||||||
|  |     BENCHMARK_ADVANCED("Large component allocation")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 world w; | ||||||
|  |                 for(int i = 0; i < SMALL; ++i) | ||||||
|  |                 { | ||||||
|  |                     auto e = w.make_entity(); | ||||||
|  |                     w.set<BigData>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.total_component_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Component memory reuse")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < SMALL; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<BigData>(e); | ||||||
|  |             entities.push_back(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 // Remove and re-add components
 | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.remove<BigData>(e); | ||||||
|  |                     w.set<BigData>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.component_count<BigData>(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST_CASE("Archetype transition benchmarks", "[benchmark]") | ||||||
|  | { | ||||||
|  |     BENCHMARK_ADVANCED("Single component addition")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |         { | ||||||
|  |             entities.push_back(w.make_entity()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.set<Health>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.archetype_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     BENCHMARK_ADVANCED("Multi-component transition")( | ||||||
|  |         Catch::Benchmark::Chronometer meter) | ||||||
|  |     { | ||||||
|  |         world w; | ||||||
|  |         std::vector<entity_id> entities; | ||||||
|  |         for(int i = 0; i < MEDIUM; ++i) | ||||||
|  |         { | ||||||
|  |             auto e = w.make_entity(); | ||||||
|  |             w.set<Position>(e); | ||||||
|  |             entities.push_back(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         meter.measure( | ||||||
|  |             [&] | ||||||
|  |             { | ||||||
|  |                 for(auto e: entities) | ||||||
|  |                 { | ||||||
|  |                     w.set<Velocity>(e); | ||||||
|  |                     w.set<Health>(e); | ||||||
|  |                 } | ||||||
|  |                 return w.archetype_count(); | ||||||
|  |             }); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue