benchmark.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #include <iostream>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <chrono>
  5. #include <gtest/gtest.h>
  6. #include <entt/entity/registry.hpp>
  7. #include <entt/entity/space.hpp>
  8. struct Position {
  9. std::uint64_t x;
  10. std::uint64_t y;
  11. };
  12. struct Velocity {
  13. std::uint64_t x;
  14. std::uint64_t y;
  15. };
  16. template<std::size_t>
  17. struct Comp { int x; };
  18. struct Timer final {
  19. Timer(): start{std::chrono::system_clock::now()} {}
  20. void elapsed() {
  21. auto now = std::chrono::system_clock::now();
  22. std::cout << std::chrono::duration<double>(now - start).count() << " seconds" << std::endl;
  23. }
  24. private:
  25. std::chrono::time_point<std::chrono::system_clock> start;
  26. };
  27. TEST(Benchmark, Construct) {
  28. entt::DefaultRegistry registry;
  29. std::cout << "Constructing 1000000 entities" << std::endl;
  30. Timer timer;
  31. for(std::uint64_t i = 0; i < 1000000L; i++) {
  32. registry.create();
  33. }
  34. timer.elapsed();
  35. }
  36. TEST(Benchmark, Destroy) {
  37. entt::DefaultRegistry registry;
  38. std::cout << "Destroying 1000000 entities" << std::endl;
  39. for(std::uint64_t i = 0; i < 1000000L; i++) {
  40. registry.create<int>();
  41. }
  42. Timer timer;
  43. for(auto entity: registry.view<int>()) {
  44. registry.destroy(entity);
  45. }
  46. timer.elapsed();
  47. }
  48. TEST(Benchmark, IterateCreateDeleteSingleComponent) {
  49. entt::DefaultRegistry registry;
  50. std::cout << "Looping 10000 times creating and deleting a random number of entities" << std::endl;
  51. Timer timer;
  52. auto view = registry.view<Position>();
  53. for(int i = 0; i < 10000; i++) {
  54. for(int j = 0; j < 10000; j++) {
  55. registry.create<Position>();
  56. }
  57. for(auto entity: view) {
  58. if(rand() % 2 == 0) {
  59. registry.destroy(entity);
  60. }
  61. }
  62. }
  63. timer.elapsed();
  64. }
  65. TEST(Benchmark, IterateSingleComponent1M) {
  66. entt::DefaultRegistry registry;
  67. std::cout << "Iterating over 1000000 entities, one component" << std::endl;
  68. for(std::uint64_t i = 0; i < 1000000L; i++) {
  69. registry.create<Position>();
  70. }
  71. Timer timer;
  72. registry.view<Position>().each([](auto, auto &) {});
  73. timer.elapsed();
  74. }
  75. TEST(Benchmark, IterateTwoComponents1M) {
  76. entt::DefaultRegistry registry;
  77. std::cout << "Iterating over 1000000 entities, two components" << std::endl;
  78. for(std::uint64_t i = 0; i < 1000000L; i++) {
  79. registry.create<Position, Velocity>();
  80. }
  81. Timer timer;
  82. registry.view<Position, Velocity>().each([](auto, auto &...) {});
  83. timer.elapsed();
  84. }
  85. TEST(Benchmark, IterateTwoComponents1MHalf) {
  86. entt::DefaultRegistry registry;
  87. std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components" << std::endl;
  88. for(std::uint64_t i = 0; i < 1000000L; i++) {
  89. auto entity = registry.create<Velocity>();
  90. if(i % 2) { registry.assign<Position>(entity); }
  91. }
  92. Timer timer;
  93. registry.view<Position, Velocity>().each([](auto, auto &...) {});
  94. timer.elapsed();
  95. }
  96. TEST(Benchmark, IterateTwoComponents1MOne) {
  97. entt::DefaultRegistry registry;
  98. std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components" << std::endl;
  99. for(std::uint64_t i = 0; i < 1000000L; i++) {
  100. auto entity = registry.create<Velocity>();
  101. if(i == 5000000L) { registry.assign<Position>(entity); }
  102. }
  103. Timer timer;
  104. registry.view<Position, Velocity>().each([](auto, auto &...) {});
  105. timer.elapsed();
  106. }
  107. TEST(Benchmark, IterateTwoComponentsPersistent1M) {
  108. entt::DefaultRegistry registry;
  109. registry.prepare<Position, Velocity>();
  110. std::cout << "Iterating over 1000000 entities, two components, persistent view" << std::endl;
  111. for(std::uint64_t i = 0; i < 1000000L; i++) {
  112. registry.create<Position, Velocity>();
  113. }
  114. Timer timer;
  115. registry.persistent<Position, Velocity>().each([](auto, auto &...) {});
  116. timer.elapsed();
  117. }
  118. TEST(Benchmark, IterateFiveComponents1M) {
  119. entt::DefaultRegistry registry;
  120. std::cout << "Iterating over 1000000 entities, five components" << std::endl;
  121. for(std::uint64_t i = 0; i < 1000000L; i++) {
  122. registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  123. }
  124. Timer timer;
  125. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
  126. timer.elapsed();
  127. }
  128. TEST(Benchmark, IterateFiveComponents1MHalf) {
  129. entt::DefaultRegistry registry;
  130. std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components" << std::endl;
  131. for(std::uint64_t i = 0; i < 1000000L; i++) {
  132. auto entity = registry.create<Velocity, Comp<1>, Comp<2>, Comp<3>>();
  133. if(i % 2) { registry.assign<Position>(entity); }
  134. }
  135. Timer timer;
  136. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
  137. timer.elapsed();
  138. }
  139. TEST(Benchmark, IterateFiveComponents1MOne) {
  140. entt::DefaultRegistry registry;
  141. std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components" << std::endl;
  142. for(std::uint64_t i = 0; i < 1000000L; i++) {
  143. auto entity = registry.create<Velocity, Comp<1>, Comp<2>, Comp<3>>();
  144. if(i == 5000000L) { registry.assign<Position>(entity); }
  145. }
  146. Timer timer;
  147. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
  148. timer.elapsed();
  149. }
  150. TEST(Benchmark, IterateFiveComponentsPersistent1M) {
  151. entt::DefaultRegistry registry;
  152. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  153. std::cout << "Iterating over 1000000 entities, five components, persistent view" << std::endl;
  154. for(std::uint64_t i = 0; i < 1000000L; i++) {
  155. registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  156. }
  157. Timer timer;
  158. registry.persistent<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
  159. timer.elapsed();
  160. }
  161. TEST(Benchmark, IterateTenComponents1M) {
  162. entt::DefaultRegistry registry;
  163. std::cout << "Iterating over 1000000 entities, ten components" << std::endl;
  164. for(std::uint64_t i = 0; i < 1000000L; i++) {
  165. registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  166. }
  167. Timer timer;
  168. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
  169. timer.elapsed();
  170. }
  171. TEST(Benchmark, IterateTenComponents1MHalf) {
  172. entt::DefaultRegistry registry;
  173. std::cout << "Iterating over 1000000 entities, ten components, half of the entities have all the components" << std::endl;
  174. for(std::uint64_t i = 0; i < 1000000L; i++) {
  175. auto entity = registry.create<Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  176. if(i % 2) { registry.assign<Position>(entity); }
  177. }
  178. Timer timer;
  179. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
  180. timer.elapsed();
  181. }
  182. TEST(Benchmark, IterateTenComponents1MOne) {
  183. entt::DefaultRegistry registry;
  184. std::cout << "Iterating over 1000000 entities, ten components, only one entity has all the components" << std::endl;
  185. for(std::uint64_t i = 0; i < 1000000L; i++) {
  186. auto entity = registry.create<Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  187. if(i == 5000000L) { registry.assign<Position>(entity); }
  188. }
  189. Timer timer;
  190. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
  191. timer.elapsed();
  192. }
  193. TEST(Benchmark, IterateTenComponentsPersistent1M) {
  194. entt::DefaultRegistry registry;
  195. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  196. std::cout << "Iterating over 1000000 entities, ten components, persistent view" << std::endl;
  197. for(std::uint64_t i = 0; i < 1000000L; i++) {
  198. registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  199. }
  200. Timer timer;
  201. registry.persistent<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
  202. timer.elapsed();
  203. }
  204. TEST(Benchmark, SortSingle) {
  205. entt::DefaultRegistry registry;
  206. std::cout << "Sort 150000 entities, one component" << std::endl;
  207. for(std::uint64_t i = 0; i < 150000L; i++) {
  208. registry.create<Position>({ i, i });
  209. }
  210. Timer timer;
  211. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  212. return lhs.x < rhs.x && lhs.y < rhs.y;
  213. });
  214. timer.elapsed();
  215. }
  216. TEST(Benchmark, SortMulti) {
  217. entt::DefaultRegistry registry;
  218. std::cout << "Sort 150000 entities, two components" << std::endl;
  219. for(std::uint64_t i = 0; i < 150000L; i++) {
  220. registry.create<Position, Velocity>({ i, i }, { i, i });
  221. }
  222. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  223. return lhs.x < rhs.x && lhs.y < rhs.y;
  224. });
  225. Timer timer;
  226. registry.sort<Velocity, Position>();
  227. timer.elapsed();
  228. }
  229. TEST(Benchmark, SpaceConstruct) {
  230. entt::DefaultRegistry registry;
  231. entt::DefaultSpace space{registry};
  232. std::cout << "Constructing 1000000 entities" << std::endl;
  233. Timer timer;
  234. for(std::uint64_t i = 0; i < 1000000L; i++) {
  235. space.create();
  236. }
  237. timer.elapsed();
  238. }
  239. TEST(Benchmark, SpaceAssign) {
  240. entt::DefaultRegistry registry;
  241. entt::DefaultSpace space{registry};
  242. std::cout << "Assigning 1000000 entities" << std::endl;
  243. for(std::uint64_t i = 0; i < 1000000L; i++) {
  244. registry.create<int>();
  245. }
  246. Timer timer;
  247. for(auto entity: registry.view<int>()) {
  248. space.assign(entity);
  249. }
  250. timer.elapsed();
  251. }
  252. TEST(Benchmark, SpaceIterateSingleComponent1M) {
  253. entt::DefaultRegistry registry;
  254. entt::DefaultSpace space{registry};
  255. std::cout << "Iterating over 1000000 entities, one component" << std::endl;
  256. for(std::uint64_t i = 0; i < 1000000L; i++) {
  257. const auto entity = registry.create<Position>();
  258. space.assign(entity);
  259. }
  260. Timer timer;
  261. space.view<Position>([](auto, auto &) {});
  262. timer.elapsed();
  263. }
  264. TEST(Benchmark, SpaceIterateTwoComponents1M) {
  265. entt::DefaultRegistry registry;
  266. entt::DefaultSpace space{registry};
  267. std::cout << "Iterating over 1000000 entities, two components" << std::endl;
  268. for(std::uint64_t i = 0; i < 1000000L; i++) {
  269. const auto entity = registry.create<Position, Velocity>();
  270. space.assign(entity);
  271. }
  272. Timer timer;
  273. space.view<Position, Velocity>([](auto, auto &...) {});
  274. timer.elapsed();
  275. }
  276. TEST(Benchmark, SpaceIterateTwoComponentsPersistent1M) {
  277. entt::DefaultRegistry registry;
  278. entt::DefaultSpace space{registry};
  279. registry.prepare<Position, Velocity>();
  280. std::cout << "Iterating over 1000000 entities, two components, persistent view" << std::endl;
  281. for(std::uint64_t i = 0; i < 1000000L; i++) {
  282. const auto entity = registry.create<Position, Velocity>();
  283. space.assign(entity);
  284. }
  285. Timer timer;
  286. space.persistent<Position, Velocity>([](auto, auto &...) {});
  287. timer.elapsed();
  288. }
  289. TEST(Benchmark, SpaceIterateFiveComponents1M) {
  290. entt::DefaultRegistry registry;
  291. entt::DefaultSpace space{registry};
  292. std::cout << "Iterating over 1000000 entities, five components" << std::endl;
  293. for(std::uint64_t i = 0; i < 1000000L; i++) {
  294. const auto entity = registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  295. space.assign(entity);
  296. }
  297. Timer timer;
  298. space.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>([](auto, auto &...) {});
  299. timer.elapsed();
  300. }
  301. TEST(Benchmark, SpaceIterateFiveComponentsPersistent1M) {
  302. entt::DefaultRegistry registry;
  303. entt::DefaultSpace space{registry};
  304. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  305. std::cout << "Iterating over 1000000 entities, five components, persistent view" << std::endl;
  306. for(std::uint64_t i = 0; i < 1000000L; i++) {
  307. const auto entity = registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  308. space.assign(entity);
  309. }
  310. Timer timer;
  311. space.persistent<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>([](auto, auto &...) {});
  312. timer.elapsed();
  313. }
  314. TEST(Benchmark, SpaceIterateTenComponents1M) {
  315. entt::DefaultRegistry registry;
  316. entt::DefaultSpace space{registry};
  317. std::cout << "Iterating over 1000000 entities, ten components" << std::endl;
  318. for(std::uint64_t i = 0; i < 1000000L; i++) {
  319. const auto entity = registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  320. space.assign(entity);
  321. }
  322. Timer timer;
  323. space.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>([](auto, auto &...) {});
  324. timer.elapsed();
  325. }
  326. TEST(Benchmark, SpaceIterateTenComponentsPersistent1M) {
  327. entt::DefaultRegistry registry;
  328. entt::DefaultSpace space{registry};
  329. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  330. std::cout << "Iterating over 1000000 entities, ten components, persistent view" << std::endl;
  331. for(std::uint64_t i = 0; i < 1000000L; i++) {
  332. const auto entity = registry.create<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  333. space.assign(entity);
  334. }
  335. Timer timer;
  336. space.persistent<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>([](auto, auto &...) {});
  337. timer.elapsed();
  338. }