benchmark.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. #include <iostream>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <chrono>
  5. #include <iterator>
  6. #include <gtest/gtest.h>
  7. #include <entt/core/type_info.hpp>
  8. #include <entt/entity/registry.hpp>
  9. struct position {
  10. std::uint64_t x;
  11. std::uint64_t y;
  12. };
  13. struct velocity {
  14. std::uint64_t x;
  15. std::uint64_t y;
  16. };
  17. template<std::size_t>
  18. struct comp { int x; };
  19. struct timer final {
  20. timer(): start{std::chrono::system_clock::now()} {}
  21. void elapsed() {
  22. auto now = std::chrono::system_clock::now();
  23. std::cout << std::chrono::duration<double>(now - start).count() << " seconds" << std::endl;
  24. }
  25. private:
  26. std::chrono::time_point<std::chrono::system_clock> start;
  27. };
  28. template<typename Func>
  29. void pathological(Func func) {
  30. entt::registry registry;
  31. for(std::uint64_t i = 0; i < 500000L; i++) {
  32. const auto entity = registry.create();
  33. registry.emplace<position>(entity);
  34. registry.emplace<velocity>(entity);
  35. registry.emplace<comp<0>>(entity);
  36. }
  37. for(auto i = 0; i < 10; ++i) {
  38. registry.each([i = 0, &registry](const auto entity) mutable {
  39. if(!(++i % 7)) { registry.remove_if_exists<position>(entity); }
  40. if(!(++i % 11)) { registry.remove_if_exists<velocity>(entity); }
  41. if(!(++i % 13)) { registry.remove_if_exists<comp<0>>(entity); }
  42. if(!(++i % 17)) { registry.destroy(entity); }
  43. });
  44. for(std::uint64_t j = 0; j < 50000L; j++) {
  45. const auto entity = registry.create();
  46. registry.emplace<position>(entity);
  47. registry.emplace<velocity>(entity);
  48. registry.emplace<comp<0>>(entity);
  49. }
  50. }
  51. func(registry, [](auto &... comp) {
  52. ((comp.x = {}), ...);
  53. });
  54. }
  55. // TEST(Benchmark, Create) {
  56. // entt::registry registry;
  57. //
  58. // std::cout << "Creating 1000000 entities" << std::endl;
  59. //
  60. // timer timer;
  61. //
  62. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  63. // registry.create();
  64. // }
  65. //
  66. // timer.elapsed();
  67. // }
  68. //
  69. // TEST(Benchmark, CreateMany) {
  70. // entt::registry registry;
  71. // std::vector<entt::entity> entities(1000000);
  72. //
  73. // std::cout << "Creating 1000000 entities at once" << std::endl;
  74. //
  75. // timer timer;
  76. // registry.create(entities.begin(), entities.end());
  77. // timer.elapsed();
  78. // }
  79. //
  80. // TEST(Benchmark, CreateManyAndEmplaceComponents) {
  81. // entt::registry registry;
  82. // std::vector<entt::entity> entities(1000000);
  83. //
  84. // std::cout << "Creating 1000000 entities at once and emplace components" << std::endl;
  85. //
  86. // timer timer;
  87. //
  88. // registry.create(entities.begin(), entities.end());
  89. //
  90. // for(const auto entity: entities) {
  91. // registry.emplace<position>(entity);
  92. // registry.emplace<velocity>(entity);
  93. // }
  94. //
  95. // timer.elapsed();
  96. // }
  97. //
  98. // TEST(Benchmark, CreateManyWithComponents) {
  99. // entt::registry registry;
  100. // std::vector<entt::entity> entities(1000000);
  101. //
  102. // std::cout << "Creating 1000000 entities at once with components" << std::endl;
  103. //
  104. // timer timer;
  105. // registry.create(entities.begin(), entities.end());
  106. // registry.insert<position>(entities.begin(), entities.end());
  107. // registry.insert<velocity>(entities.begin(), entities.end());
  108. // timer.elapsed();
  109. // }
  110. //
  111. // TEST(Benchmark, Remove) {
  112. // entt::registry registry;
  113. // std::vector<entt::entity> entities(1000000);
  114. //
  115. // std::cout << "Removing 1000000 components from their entities" << std::endl;
  116. //
  117. // registry.create(entities.begin(), entities.end());
  118. // registry.insert<int>(entities.begin(), entities.end());
  119. //
  120. // timer timer;
  121. //
  122. // for(auto entity: registry.view<int>()) {
  123. // registry.remove<int>(entity);
  124. // }
  125. //
  126. // timer.elapsed();
  127. // }
  128. //
  129. // TEST(Benchmark, RemoveMany) {
  130. // entt::registry registry;
  131. // std::vector<entt::entity> entities(1000000);
  132. //
  133. // std::cout << "Removing 999999 components from their entities at once" << std::endl;
  134. //
  135. // registry.create(entities.begin(), entities.end());
  136. // registry.insert<int>(entities.begin(), entities.end());
  137. //
  138. // timer timer;
  139. // auto view = registry.view<int>();
  140. // registry.remove<int>(++view.begin(), view.end());
  141. // timer.elapsed();
  142. // }
  143. //
  144. // TEST(Benchmark, RemoveAll) {
  145. // entt::registry registry;
  146. // std::vector<entt::entity> entities(1000000);
  147. //
  148. // std::cout << "Removing 1000000 components from their entities at once" << std::endl;
  149. //
  150. // registry.create(entities.begin(), entities.end());
  151. // registry.insert<int>(entities.begin(), entities.end());
  152. //
  153. // timer timer;
  154. // auto view = registry.view<int>();
  155. // registry.remove<int>(view.begin(), view.end());
  156. // timer.elapsed();
  157. // }
  158. //
  159. // TEST(Benchmark, Recycle) {
  160. // entt::registry registry;
  161. // std::vector<entt::entity> entities(1000000);
  162. //
  163. // std::cout << "Recycling 1000000 entities" << std::endl;
  164. //
  165. // registry.create(entities.begin(), entities.end());
  166. //
  167. // registry.each([&registry](auto entity) {
  168. // registry.destroy(entity);
  169. // });
  170. //
  171. // timer timer;
  172. //
  173. // for(auto next = entities.size(); next; --next) {
  174. // registry.create();
  175. // }
  176. //
  177. // timer.elapsed();
  178. // }
  179. //
  180. // TEST(Benchmark, RecycleMany) {
  181. // entt::registry registry;
  182. // std::vector<entt::entity> entities(1000000);
  183. //
  184. // std::cout << "Recycling 1000000 entities" << std::endl;
  185. //
  186. // registry.create(entities.begin(), entities.end());
  187. //
  188. // registry.each([&registry](auto entity) {
  189. // registry.destroy(entity);
  190. // });
  191. //
  192. // timer timer;
  193. // registry.create(entities.begin(), entities.end());
  194. // timer.elapsed();
  195. // }
  196. //
  197. // TEST(Benchmark, Destroy) {
  198. // entt::registry registry;
  199. // std::vector<entt::entity> entities(1000000);
  200. //
  201. // std::cout << "Destroying 1000000 entities" << std::endl;
  202. //
  203. // registry.create(entities.begin(), entities.end());
  204. // registry.insert<int>(entities.begin(), entities.end());
  205. //
  206. // timer timer;
  207. //
  208. // for(auto entity: registry.view<int>()) {
  209. // registry.destroy(entity);
  210. // }
  211. //
  212. // timer.elapsed();
  213. // }
  214. //
  215. // TEST(Benchmark, DestroyMany) {
  216. // entt::registry registry;
  217. // std::vector<entt::entity> entities(1000000);
  218. //
  219. // std::cout << "Destroying 1000000 entities" << std::endl;
  220. //
  221. // registry.create(entities.begin(), entities.end());
  222. // registry.insert<int>(entities.begin(), entities.end());
  223. //
  224. // timer timer;
  225. // auto view = registry.view<int>();
  226. // registry.destroy(view.begin(), view.end());
  227. // timer.elapsed();
  228. // }
  229. //
  230. // TEST(Benchmark, IterateSingleComponent1M) {
  231. // entt::registry registry;
  232. //
  233. // std::cout << "Iterating over 1000000 entities, one component" << std::endl;
  234. //
  235. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  236. // const auto entity = registry.create();
  237. // registry.emplace<position>(entity);
  238. // }
  239. //
  240. // auto test = [&](auto func) {
  241. // timer timer;
  242. // registry.view<position>().each(func);
  243. // timer.elapsed();
  244. // };
  245. //
  246. // test([](auto &... comp) {
  247. // ((comp.x = {}), ...);
  248. // });
  249. // }
  250. //
  251. // TEST(Benchmark, IterateSingleComponentRuntime1M) {
  252. // entt::registry registry;
  253. //
  254. // std::cout << "Iterating over 1000000 entities, one component, runtime view" << std::endl;
  255. //
  256. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  257. // const auto entity = registry.create();
  258. // registry.emplace<position>(entity);
  259. // }
  260. //
  261. // auto test = [&](auto func) {
  262. // entt::id_type types[] = { entt::type_hash<position>::value() };
  263. //
  264. // timer timer;
  265. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  266. // timer.elapsed();
  267. // };
  268. //
  269. // test([&registry](auto entity) {
  270. // registry.get<position>(entity).x = {};
  271. // });
  272. // }
  273. //
  274. // TEST(Benchmark, IterateTwoComponents1M) {
  275. // entt::registry registry;
  276. //
  277. // std::cout << "Iterating over 1000000 entities, two components" << std::endl;
  278. //
  279. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  280. // const auto entity = registry.create();
  281. // registry.emplace<position>(entity);
  282. // registry.emplace<velocity>(entity);
  283. // }
  284. //
  285. // auto test = [&](auto func) {
  286. // timer timer;
  287. // registry.view<position, velocity>().each(func);
  288. // timer.elapsed();
  289. // };
  290. //
  291. // test([](auto &... comp) {
  292. // ((comp.x = {}), ...);
  293. // });
  294. // }
  295. //
  296. // TEST(Benchmark, IterateTwoComponents1MHalf) {
  297. // entt::registry registry;
  298. //
  299. // std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components" << std::endl;
  300. //
  301. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  302. // const auto entity = registry.create();
  303. // registry.emplace<velocity>(entity);
  304. //
  305. // if(i % 2) {
  306. // registry.emplace<position>(entity);
  307. // }
  308. // }
  309. //
  310. // auto test = [&](auto func) {
  311. // timer timer;
  312. // registry.view<position, velocity>().each(func);
  313. // timer.elapsed();
  314. // };
  315. //
  316. // test([](auto &... comp) {
  317. // ((comp.x = {}), ...);
  318. // });
  319. // }
  320. //
  321. // TEST(Benchmark, IterateTwoComponents1MOne) {
  322. // entt::registry registry;
  323. //
  324. // std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components" << std::endl;
  325. //
  326. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  327. // const auto entity = registry.create();
  328. // registry.emplace<velocity>(entity);
  329. //
  330. // if(i == 500000L) {
  331. // registry.emplace<position>(entity);
  332. // }
  333. // }
  334. //
  335. // auto test = [&](auto func) {
  336. // timer timer;
  337. // registry.view<position, velocity>().each(func);
  338. // timer.elapsed();
  339. // };
  340. //
  341. // test([](auto &... comp) {
  342. // ((comp.x = {}), ...);
  343. // });
  344. // }
  345. //
  346. // TEST(Benchmark, IterateTwoComponentsNonOwningGroup1M) {
  347. // entt::registry registry;
  348. // const auto group = registry.group<>(entt::get<position, velocity>);
  349. //
  350. // std::cout << "Iterating over 1000000 entities, two components, non owning group" << std::endl;
  351. //
  352. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  353. // const auto entity = registry.create();
  354. // registry.emplace<position>(entity);
  355. // registry.emplace<velocity>(entity);
  356. // }
  357. //
  358. // auto test = [&](auto func) {
  359. // timer timer;
  360. // group.each(func);
  361. // timer.elapsed();
  362. // };
  363. //
  364. // test([](auto &... comp) {
  365. // ((comp.x = {}), ...);
  366. // });
  367. // }
  368. //
  369. // TEST(Benchmark, IterateTwoComponentsFullOwningGroup1M) {
  370. // entt::registry registry;
  371. // const auto group = registry.group<position, velocity>();
  372. //
  373. // std::cout << "Iterating over 1000000 entities, two components, full owning group" << std::endl;
  374. //
  375. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  376. // const auto entity = registry.create();
  377. // registry.emplace<position>(entity);
  378. // registry.emplace<velocity>(entity);
  379. // }
  380. //
  381. // auto test = [&](auto func) {
  382. // timer timer;
  383. // group.each(func);
  384. // timer.elapsed();
  385. // };
  386. //
  387. // test([](auto &... comp) {
  388. // ((comp.x = {}), ...);
  389. // });
  390. // }
  391. //
  392. // TEST(Benchmark, IterateTwoComponentsPartialOwningGroup1M) {
  393. // entt::registry registry;
  394. // const auto group = registry.group<position>(entt::get<velocity>);
  395. //
  396. // std::cout << "Iterating over 1000000 entities, two components, partial owning group" << std::endl;
  397. //
  398. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  399. // const auto entity = registry.create();
  400. // registry.emplace<position>(entity);
  401. // registry.emplace<velocity>(entity);
  402. // }
  403. //
  404. // auto test = [&](auto func) {
  405. // timer timer;
  406. // group.each(func);
  407. // timer.elapsed();
  408. // };
  409. //
  410. // test([](auto &... comp) {
  411. // ((comp.x = {}), ...);
  412. // });
  413. // }
  414. //
  415. // TEST(Benchmark, IterateTwoComponentsRuntime1M) {
  416. // entt::registry registry;
  417. //
  418. // std::cout << "Iterating over 1000000 entities, two components, runtime view" << std::endl;
  419. //
  420. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  421. // const auto entity = registry.create();
  422. // registry.emplace<position>(entity);
  423. // registry.emplace<velocity>(entity);
  424. // }
  425. //
  426. // auto test = [&](auto func) {
  427. // entt::id_type types[] = {
  428. // entt::type_hash<position>::value(),
  429. // entt::type_hash<velocity>::value()
  430. // };
  431. //
  432. // timer timer;
  433. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  434. // timer.elapsed();
  435. // };
  436. //
  437. // test([&registry](auto entity) {
  438. // registry.get<position>(entity).x = {};
  439. // registry.get<velocity>(entity).x = {};
  440. // });
  441. // }
  442. //
  443. // TEST(Benchmark, IterateTwoComponentsRuntime1MHalf) {
  444. // entt::registry registry;
  445. //
  446. // std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components, runtime view" << std::endl;
  447. //
  448. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  449. // const auto entity = registry.create();
  450. // registry.emplace<velocity>(entity);
  451. //
  452. // if(i % 2) {
  453. // registry.emplace<position>(entity);
  454. // }
  455. // }
  456. //
  457. // auto test = [&](auto func) {
  458. // entt::id_type types[] = {
  459. // entt::type_hash<position>::value(),
  460. // entt::type_hash<velocity>::value()
  461. // };
  462. //
  463. // timer timer;
  464. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  465. // timer.elapsed();
  466. // };
  467. //
  468. // test([&registry](auto entity) {
  469. // registry.get<position>(entity).x = {};
  470. // registry.get<velocity>(entity).x = {};
  471. // });
  472. // }
  473. //
  474. // TEST(Benchmark, IterateTwoComponentsRuntime1MOne) {
  475. // entt::registry registry;
  476. //
  477. // std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components, runtime view" << std::endl;
  478. //
  479. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  480. // const auto entity = registry.create();
  481. // registry.emplace<velocity>(entity);
  482. //
  483. // if(i == 500000L) {
  484. // registry.emplace<position>(entity);
  485. // }
  486. // }
  487. //
  488. // auto test = [&](auto func) {
  489. // entt::id_type types[] = {
  490. // entt::type_hash<position>::value(),
  491. // entt::type_hash<velocity>::value()
  492. // };
  493. //
  494. // timer timer;
  495. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  496. // timer.elapsed();
  497. // };
  498. //
  499. // test([&registry](auto entity) {
  500. // registry.get<position>(entity).x = {};
  501. // registry.get<velocity>(entity).x = {};
  502. // });
  503. // }
  504. //
  505. // TEST(Benchmark, IterateThreeComponents1M) {
  506. // entt::registry registry;
  507. //
  508. // std::cout << "Iterating over 1000000 entities, three components" << std::endl;
  509. //
  510. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  511. // const auto entity = registry.create();
  512. // registry.emplace<position>(entity);
  513. // registry.emplace<velocity>(entity);
  514. // registry.emplace<comp<0>>(entity);
  515. // }
  516. //
  517. // auto test = [&](auto func) {
  518. // timer timer;
  519. // registry.view<position, velocity, comp<0>>().each(func);
  520. // timer.elapsed();
  521. // };
  522. //
  523. // test([](auto &... comp) {
  524. // ((comp.x = {}), ...);
  525. // });
  526. // }
  527. //
  528. // TEST(Benchmark, IterateThreeComponents1MHalf) {
  529. // entt::registry registry;
  530. //
  531. // std::cout << "Iterating over 1000000 entities, three components, half of the entities have all the components" << std::endl;
  532. //
  533. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  534. // const auto entity = registry.create();
  535. // registry.emplace<velocity>(entity);
  536. // registry.emplace<comp<0>>(entity);
  537. //
  538. // if(i % 2) {
  539. // registry.emplace<position>(entity);
  540. // }
  541. // }
  542. //
  543. // auto test = [&](auto func) {
  544. // timer timer;
  545. // registry.view<position, velocity, comp<0>>().each(func);
  546. // timer.elapsed();
  547. // };
  548. //
  549. // test([](auto &... comp) {
  550. // ((comp.x = {}), ...);
  551. // });
  552. // }
  553. //
  554. // TEST(Benchmark, IterateThreeComponents1MOne) {
  555. // entt::registry registry;
  556. //
  557. // std::cout << "Iterating over 1000000 entities, three components, only one entity has all the components" << std::endl;
  558. //
  559. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  560. // const auto entity = registry.create();
  561. // registry.emplace<velocity>(entity);
  562. // registry.emplace<comp<0>>(entity);
  563. //
  564. // if(i == 500000L) {
  565. // registry.emplace<position>(entity);
  566. // }
  567. // }
  568. //
  569. // auto test = [&](auto func) {
  570. // timer timer;
  571. // registry.view<position, velocity, comp<0>>().each(func);
  572. // timer.elapsed();
  573. // };
  574. //
  575. // test([](auto &... comp) {
  576. // ((comp.x = {}), ...);
  577. // });
  578. // }
  579. //
  580. // TEST(Benchmark, IterateThreeComponentsNonOwningGroup1M) {
  581. // entt::registry registry;
  582. // const auto group = registry.group<>(entt::get<position, velocity, comp<0>>);
  583. //
  584. // std::cout << "Iterating over 1000000 entities, three components, non owning group" << std::endl;
  585. //
  586. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  587. // const auto entity = registry.create();
  588. // registry.emplace<position>(entity);
  589. // registry.emplace<velocity>(entity);
  590. // registry.emplace<comp<0>>(entity);
  591. // }
  592. //
  593. // auto test = [&](auto func) {
  594. // timer timer;
  595. // group.each(func);
  596. // timer.elapsed();
  597. // };
  598. //
  599. // test([](auto &... comp) {
  600. // ((comp.x = {}), ...);
  601. // });
  602. // }
  603. //
  604. // TEST(Benchmark, IterateThreeComponentsFullOwningGroup1M) {
  605. // entt::registry registry;
  606. // const auto group = registry.group<position, velocity, comp<0>>();
  607. //
  608. // std::cout << "Iterating over 1000000 entities, three components, full owning group" << std::endl;
  609. //
  610. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  611. // const auto entity = registry.create();
  612. // registry.emplace<position>(entity);
  613. // registry.emplace<velocity>(entity);
  614. // registry.emplace<comp<0>>(entity);
  615. // }
  616. //
  617. // auto test = [&](auto func) {
  618. // timer timer;
  619. // group.each(func);
  620. // timer.elapsed();
  621. // };
  622. //
  623. // test([](auto &... comp) {
  624. // ((comp.x = {}), ...);
  625. // });
  626. // }
  627. //
  628. // TEST(Benchmark, IterateThreeComponentsPartialOwningGroup1M) {
  629. // entt::registry registry;
  630. // const auto group = registry.group<position, velocity>(entt::get<comp<0>>);
  631. //
  632. // std::cout << "Iterating over 1000000 entities, three components, partial owning group" << std::endl;
  633. //
  634. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  635. // const auto entity = registry.create();
  636. // registry.emplace<position>(entity);
  637. // registry.emplace<velocity>(entity);
  638. // registry.emplace<comp<0>>(entity);
  639. // }
  640. //
  641. // auto test = [&](auto func) {
  642. // timer timer;
  643. // group.each(func);
  644. // timer.elapsed();
  645. // };
  646. //
  647. // test([](auto &... comp) {
  648. // ((comp.x = {}), ...);
  649. // });
  650. // }
  651. //
  652. // TEST(Benchmark, IterateThreeComponentsRuntime1M) {
  653. // entt::registry registry;
  654. //
  655. // std::cout << "Iterating over 1000000 entities, three components, runtime view" << std::endl;
  656. //
  657. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  658. // const auto entity = registry.create();
  659. // registry.emplace<position>(entity);
  660. // registry.emplace<velocity>(entity);
  661. // registry.emplace<comp<0>>(entity);
  662. // }
  663. //
  664. // auto test = [&](auto func) {
  665. // entt::id_type types[] = {
  666. // entt::type_hash<position>::value(),
  667. // entt::type_hash<velocity>::value(),
  668. // entt::type_hash<comp<0>>::value()
  669. // };
  670. //
  671. // timer timer;
  672. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  673. // timer.elapsed();
  674. // };
  675. //
  676. // test([&registry](auto entity) {
  677. // registry.get<position>(entity).x = {};
  678. // registry.get<velocity>(entity).x = {};
  679. // registry.get<comp<0>>(entity).x = {};
  680. // });
  681. // }
  682. //
  683. // TEST(Benchmark, IterateThreeComponentsRuntime1MHalf) {
  684. // entt::registry registry;
  685. //
  686. // std::cout << "Iterating over 1000000 entities, three components, half of the entities have all the components, runtime view" << std::endl;
  687. //
  688. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  689. // const auto entity = registry.create();
  690. // registry.emplace<velocity>(entity);
  691. // registry.emplace<comp<0>>(entity);
  692. //
  693. // if(i % 2) {
  694. // registry.emplace<position>(entity);
  695. // }
  696. // }
  697. //
  698. // auto test = [&](auto func) {
  699. // entt::id_type types[] = {
  700. // entt::type_hash<position>::value(),
  701. // entt::type_hash<velocity>::value(),
  702. // entt::type_hash<comp<0>>::value()
  703. // };
  704. //
  705. // timer timer;
  706. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  707. // timer.elapsed();
  708. // };
  709. //
  710. // test([&registry](auto entity) {
  711. // registry.get<position>(entity).x = {};
  712. // registry.get<velocity>(entity).x = {};
  713. // registry.get<comp<0>>(entity).x = {};
  714. // });
  715. // }
  716. //
  717. // TEST(Benchmark, IterateThreeComponentsRuntime1MOne) {
  718. // entt::registry registry;
  719. //
  720. // std::cout << "Iterating over 1000000 entities, three components, only one entity has all the components, runtime view" << std::endl;
  721. //
  722. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  723. // const auto entity = registry.create();
  724. // registry.emplace<velocity>(entity);
  725. // registry.emplace<comp<0>>(entity);
  726. //
  727. // if(i == 500000L) {
  728. // registry.emplace<position>(entity);
  729. // }
  730. // }
  731. //
  732. // auto test = [&](auto func) {
  733. // entt::id_type types[] = {
  734. // entt::type_hash<position>::value(),
  735. // entt::type_hash<velocity>::value(),
  736. // entt::type_hash<comp<0>>::value()
  737. // };
  738. //
  739. // timer timer;
  740. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  741. // timer.elapsed();
  742. // };
  743. //
  744. // test([&registry](auto entity) {
  745. // registry.get<position>(entity).x = {};
  746. // registry.get<velocity>(entity).x = {};
  747. // registry.get<comp<0>>(entity).x = {};
  748. // });
  749. // }
  750. //
  751. // TEST(Benchmark, IterateFiveComponents1M) {
  752. // entt::registry registry;
  753. //
  754. // std::cout << "Iterating over 1000000 entities, five components" << std::endl;
  755. //
  756. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  757. // const auto entity = registry.create();
  758. // registry.emplace<position>(entity);
  759. // registry.emplace<velocity>(entity);
  760. // registry.emplace<comp<0>>(entity);
  761. // registry.emplace<comp<1>>(entity);
  762. // registry.emplace<comp<2>>(entity);
  763. // }
  764. //
  765. // auto test = [&](auto func) {
  766. // timer timer;
  767. // registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  768. // timer.elapsed();
  769. // };
  770. //
  771. // test([](auto &... comp) {
  772. // ((comp.x = {}), ...);
  773. // });
  774. // }
  775. //
  776. // TEST(Benchmark, IterateFiveComponents1MHalf) {
  777. // entt::registry registry;
  778. //
  779. // std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components" << std::endl;
  780. //
  781. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  782. // const auto entity = registry.create();
  783. // registry.emplace<velocity>(entity);
  784. // registry.emplace<comp<0>>(entity);
  785. // registry.emplace<comp<1>>(entity);
  786. // registry.emplace<comp<2>>(entity);
  787. //
  788. // if(i % 2) {
  789. // registry.emplace<position>(entity);
  790. // }
  791. // }
  792. //
  793. // auto test = [&](auto func) {
  794. // timer timer;
  795. // registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  796. // timer.elapsed();
  797. // };
  798. //
  799. // test([](auto &... comp) {
  800. // ((comp.x = {}), ...);
  801. // });
  802. // }
  803. //
  804. // TEST(Benchmark, IterateFiveComponents1MOne) {
  805. // entt::registry registry;
  806. //
  807. // std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components" << std::endl;
  808. //
  809. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  810. // const auto entity = registry.create();
  811. // registry.emplace<velocity>(entity);
  812. // registry.emplace<comp<0>>(entity);
  813. // registry.emplace<comp<1>>(entity);
  814. // registry.emplace<comp<2>>(entity);
  815. //
  816. // if(i == 500000L) {
  817. // registry.emplace<position>(entity);
  818. // }
  819. // }
  820. //
  821. // auto test = [&](auto func) {
  822. // timer timer;
  823. // registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  824. // timer.elapsed();
  825. // };
  826. //
  827. // test([](auto &... comp) {
  828. // ((comp.x = {}), ...);
  829. // });
  830. // }
  831. //
  832. // TEST(Benchmark, IterateFiveComponentsNonOwningGroup1M) {
  833. // entt::registry registry;
  834. // const auto group = registry.group<>(entt::get<position, velocity, comp<0>, comp<1>, comp<2>>);
  835. //
  836. // std::cout << "Iterating over 1000000 entities, five components, non owning group" << std::endl;
  837. //
  838. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  839. // const auto entity = registry.create();
  840. // registry.emplace<position>(entity);
  841. // registry.emplace<velocity>(entity);
  842. // registry.emplace<comp<0>>(entity);
  843. // registry.emplace<comp<1>>(entity);
  844. // registry.emplace<comp<2>>(entity);
  845. // }
  846. //
  847. // auto test = [&](auto func) {
  848. // timer timer;
  849. // group.each(func);
  850. // timer.elapsed();
  851. // };
  852. //
  853. // test([](auto &... comp) {
  854. // ((comp.x = {}), ...);
  855. // });
  856. // }
  857. //
  858. // TEST(Benchmark, IterateFiveComponentsFullOwningGroup1M) {
  859. // entt::registry registry;
  860. // const auto group = registry.group<position, velocity, comp<0>, comp<1>, comp<2>>();
  861. //
  862. // std::cout << "Iterating over 1000000 entities, five components, full owning group" << std::endl;
  863. //
  864. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  865. // const auto entity = registry.create();
  866. // registry.emplace<position>(entity);
  867. // registry.emplace<velocity>(entity);
  868. // registry.emplace<comp<0>>(entity);
  869. // registry.emplace<comp<1>>(entity);
  870. // registry.emplace<comp<2>>(entity);
  871. // }
  872. //
  873. // auto test = [&](auto func) {
  874. // timer timer;
  875. // group.each(func);
  876. // timer.elapsed();
  877. // };
  878. //
  879. // test([](auto &... comp) {
  880. // ((comp.x = {}), ...);
  881. // });
  882. // }
  883. //
  884. // TEST(Benchmark, IterateFiveComponentsPartialFourOfFiveOwningGroup1M) {
  885. // entt::registry registry;
  886. // const auto group = registry.group<position, velocity, comp<0>, comp<1>>(entt::get<comp<2>>);
  887. //
  888. // std::cout << "Iterating over 1000000 entities, five components, partial (4 of 5) owning group" << std::endl;
  889. //
  890. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  891. // const auto entity = registry.create();
  892. // registry.emplace<position>(entity);
  893. // registry.emplace<velocity>(entity);
  894. // registry.emplace<comp<0>>(entity);
  895. // registry.emplace<comp<1>>(entity);
  896. // registry.emplace<comp<2>>(entity);
  897. // }
  898. //
  899. // auto test = [&](auto func) {
  900. // timer timer;
  901. // group.each(func);
  902. // timer.elapsed();
  903. // };
  904. //
  905. // test([](auto &... comp) {
  906. // ((comp.x = {}), ...);
  907. // });
  908. // }
  909. //
  910. // TEST(Benchmark, IterateFiveComponentsPartialThreeOfFiveOwningGroup1M) {
  911. // entt::registry registry;
  912. // const auto group = registry.group<position, velocity, comp<0>>(entt::get<comp<1>, comp<2>>);
  913. //
  914. // std::cout << "Iterating over 1000000 entities, five components, partial (3 of 5) owning group" << std::endl;
  915. //
  916. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  917. // const auto entity = registry.create();
  918. // registry.emplace<position>(entity);
  919. // registry.emplace<velocity>(entity);
  920. // registry.emplace<comp<0>>(entity);
  921. // registry.emplace<comp<1>>(entity);
  922. // registry.emplace<comp<2>>(entity);
  923. // }
  924. //
  925. // auto test = [&](auto func) {
  926. // timer timer;
  927. // group.each(func);
  928. // timer.elapsed();
  929. // };
  930. //
  931. // test([](auto &... comp) {
  932. // ((comp.x = {}), ...);
  933. // });
  934. // }
  935. //
  936. // TEST(Benchmark, IterateFiveComponentsRuntime1M) {
  937. // entt::registry registry;
  938. //
  939. // std::cout << "Iterating over 1000000 entities, five components, runtime view" << std::endl;
  940. //
  941. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  942. // const auto entity = registry.create();
  943. // registry.emplace<position>(entity);
  944. // registry.emplace<velocity>(entity);
  945. // registry.emplace<comp<0>>(entity);
  946. // registry.emplace<comp<1>>(entity);
  947. // registry.emplace<comp<2>>(entity);
  948. // }
  949. //
  950. // auto test = [&](auto func) {
  951. // entt::id_type types[] = {
  952. // entt::type_hash<position>::value(),
  953. // entt::type_hash<velocity>::value(),
  954. // entt::type_hash<comp<0>>::value(),
  955. // entt::type_hash<comp<1>>::value(),
  956. // entt::type_hash<comp<2>>::value()
  957. // };
  958. //
  959. // timer timer;
  960. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  961. // timer.elapsed();
  962. // };
  963. //
  964. // test([&registry](auto entity) {
  965. // registry.get<position>(entity).x = {};
  966. // registry.get<velocity>(entity).x = {};
  967. // registry.get<comp<0>>(entity).x = {};
  968. // registry.get<comp<1>>(entity).x = {};
  969. // registry.get<comp<2>>(entity).x = {};
  970. // });
  971. // }
  972. //
  973. // TEST(Benchmark, IterateFiveComponentsRuntime1MHalf) {
  974. // entt::registry registry;
  975. //
  976. // std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components, runtime view" << std::endl;
  977. //
  978. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  979. // const auto entity = registry.create();
  980. // registry.emplace<velocity>(entity);
  981. // registry.emplace<comp<0>>(entity);
  982. // registry.emplace<comp<1>>(entity);
  983. // registry.emplace<comp<2>>(entity);
  984. //
  985. // if(i % 2) {
  986. // registry.emplace<position>(entity);
  987. // }
  988. // }
  989. //
  990. // auto test = [&](auto func) {
  991. // entt::id_type types[] = {
  992. // entt::type_hash<position>::value(),
  993. // entt::type_hash<velocity>::value(),
  994. // entt::type_hash<comp<0>>::value(),
  995. // entt::type_hash<comp<1>>::value(),
  996. // entt::type_hash<comp<2>>::value()
  997. // };
  998. //
  999. // timer timer;
  1000. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  1001. // timer.elapsed();
  1002. // };
  1003. //
  1004. // test([&registry](auto entity) {
  1005. // registry.get<position>(entity).x = {};
  1006. // registry.get<velocity>(entity).x = {};
  1007. // registry.get<comp<0>>(entity).x = {};
  1008. // registry.get<comp<1>>(entity).x = {};
  1009. // registry.get<comp<2>>(entity).x = {};
  1010. // });
  1011. // }
  1012. //
  1013. // TEST(Benchmark, IterateFiveComponentsRuntime1MOne) {
  1014. // entt::registry registry;
  1015. //
  1016. // std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components, runtime view" << std::endl;
  1017. //
  1018. // for(std::uint64_t i = 0; i < 1000000L; i++) {
  1019. // const auto entity = registry.create();
  1020. // registry.emplace<velocity>(entity);
  1021. // registry.emplace<comp<0>>(entity);
  1022. // registry.emplace<comp<1>>(entity);
  1023. // registry.emplace<comp<2>>(entity);
  1024. //
  1025. // if(i == 500000L) {
  1026. // registry.emplace<position>(entity);
  1027. // }
  1028. // }
  1029. //
  1030. // auto test = [&](auto func) {
  1031. // entt::id_type types[] = {
  1032. // entt::type_hash<position>::value(),
  1033. // entt::type_hash<velocity>::value(),
  1034. // entt::type_hash<comp<0>>::value(),
  1035. // entt::type_hash<comp<1>>::value(),
  1036. // entt::type_hash<comp<2>>::value()
  1037. // };
  1038. //
  1039. // timer timer;
  1040. // registry.runtime_view(std::begin(types), std::end(types)).each(func);
  1041. // timer.elapsed();
  1042. // };
  1043. //
  1044. // test([&registry](auto entity) {
  1045. // registry.get<position>(entity).x = {};
  1046. // registry.get<velocity>(entity).x = {};
  1047. // registry.get<comp<0>>(entity).x = {};
  1048. // registry.get<comp<1>>(entity).x = {};
  1049. // registry.get<comp<2>>(entity).x = {};
  1050. // });
  1051. // }
  1052. //
  1053. // TEST(Benchmark, IteratePathological) {
  1054. // std::cout << "Pathological case" << std::endl;
  1055. //
  1056. // pathological([](auto &registry, auto func) {
  1057. // timer timer;
  1058. // registry.template view<position, velocity, comp<0>>().each(func);
  1059. // timer.elapsed();
  1060. // });
  1061. // }
  1062. //
  1063. // TEST(Benchmark, IteratePathologicalNonOwningGroup) {
  1064. // std::cout << "Pathological case (non-owning group)" << std::endl;
  1065. //
  1066. // pathological([](auto &registry, auto func) {
  1067. // auto group = registry.template group<>(entt::get<position, velocity, comp<0>>);
  1068. //
  1069. // timer timer;
  1070. // group.each(func);
  1071. // timer.elapsed();
  1072. // });
  1073. // }
  1074. //
  1075. // TEST(Benchmark, IteratePathologicalFullOwningGroup) {
  1076. // std::cout << "Pathological case (full-owning group)" << std::endl;
  1077. //
  1078. // pathological([](auto &registry, auto func) {
  1079. // auto group = registry.template group<position, velocity, comp<0>>();
  1080. //
  1081. // timer timer;
  1082. // group.each(func);
  1083. // timer.elapsed();
  1084. // });
  1085. // }
  1086. //
  1087. // TEST(Benchmark, IteratePathologicalPartialOwningGroup) {
  1088. // std::cout << "Pathological case (partial-owning group)" << std::endl;
  1089. //
  1090. // pathological([](auto &registry, auto func) {
  1091. // auto group = registry.template group<position, velocity>(entt::get<comp<0>>);
  1092. //
  1093. // timer timer;
  1094. // group.each(func);
  1095. // timer.elapsed();
  1096. // });
  1097. // }
  1098. TEST(Benchmark, SortSingle) {
  1099. entt::registry registry;
  1100. std::cout << "Sort 150000 entities, one component" << std::endl;
  1101. for(std::uint64_t i = 0; i < 150000L; i++) {
  1102. const auto entity = registry.create();
  1103. registry.emplace<position>(entity, i, i);
  1104. }
  1105. timer timer;
  1106. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  1107. return lhs.x < rhs.x && lhs.y < rhs.y;
  1108. });
  1109. timer.elapsed();
  1110. }
  1111. TEST(Benchmark, SortMulti) {
  1112. entt::registry registry;
  1113. std::cout << "Sort 150000 entities, two components" << std::endl;
  1114. for(std::uint64_t i = 0; i < 150000L; i++) {
  1115. const auto entity = registry.create();
  1116. registry.emplace<position>(entity, i, i);
  1117. registry.emplace<velocity>(entity, i, i);
  1118. }
  1119. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  1120. return lhs.x < rhs.x && lhs.y < rhs.y;
  1121. });
  1122. timer timer;
  1123. registry.sort<velocity, position>();
  1124. timer.elapsed();
  1125. }
  1126. TEST(Benchmark, AlmostSortedStdSort) {
  1127. entt::registry registry;
  1128. entt::entity entities[3]{};
  1129. std::cout << "Sort 150000 entities, almost sorted, std::sort" << std::endl;
  1130. for(std::uint64_t i = 0; i < 150000L; i++) {
  1131. const auto entity = registry.create();
  1132. registry.emplace<position>(entity, i, i);
  1133. if(!(i % 50000)) {
  1134. entities[i / 50000] = entity;
  1135. }
  1136. }
  1137. for(std::uint64_t i = 0; i < 3; ++i) {
  1138. registry.destroy(entities[i]);
  1139. const auto entity = registry.create();
  1140. registry.emplace<position>(entity, 50000 * i, 50000 * i);
  1141. }
  1142. timer timer;
  1143. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  1144. return lhs.x > rhs.x && lhs.y > rhs.y;
  1145. });
  1146. timer.elapsed();
  1147. }
  1148. TEST(Benchmark, AlmostSortedInsertionSort) {
  1149. entt::registry registry;
  1150. entt::entity entities[3]{};
  1151. std::cout << "Sort 150000 entities, almost sorted, insertion sort" << std::endl;
  1152. for(std::uint64_t i = 0; i < 150000L; i++) {
  1153. const auto entity = registry.create();
  1154. registry.emplace<position>(entity, i, i);
  1155. if(!(i % 50000)) {
  1156. entities[i / 50000] = entity;
  1157. }
  1158. }
  1159. for(std::uint64_t i = 0; i < 3; ++i) {
  1160. registry.destroy(entities[i]);
  1161. const auto entity = registry.create();
  1162. registry.emplace<position>(entity, 50000 * i, 50000 * i);
  1163. }
  1164. timer timer;
  1165. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  1166. return lhs.x > rhs.x && lhs.y > rhs.y;
  1167. }, entt::insertion_sort{});
  1168. timer.elapsed();
  1169. }