benchmark.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. #include <iostream>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <chrono>
  5. #include <iterator>
  6. #include <gtest/gtest.h>
  7. #include <entt/entity/registry.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();
  41. }
  42. Timer timer;
  43. registry.each([&registry](auto entity) {
  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. const auto entity = registry.create();
  56. registry.assign<Position>(entity);
  57. }
  58. for(auto entity: view) {
  59. if(rand() % 2 == 0) {
  60. registry.destroy(entity);
  61. }
  62. }
  63. }
  64. timer.elapsed();
  65. }
  66. TEST(Benchmark, IterateSingleComponent1M) {
  67. entt::DefaultRegistry registry;
  68. std::cout << "Iterating over 1000000 entities, one component" << std::endl;
  69. for(std::uint64_t i = 0; i < 1000000L; i++) {
  70. const auto entity = registry.create();
  71. registry.assign<Position>(entity);
  72. }
  73. auto test = [&registry](auto func) {
  74. Timer timer;
  75. registry.view<Position>().each(func);
  76. timer.elapsed();
  77. };
  78. test([](auto, const auto &) {});
  79. test([](auto, auto &... comp) {
  80. using accumulator_type = int[];
  81. accumulator_type accumulator = { (comp.x = {}, 0)... };
  82. (void)accumulator;
  83. });
  84. }
  85. TEST(Benchmark, IterateSingleComponentRaw1M) {
  86. entt::DefaultRegistry registry;
  87. std::cout << "Iterating over 1000000 entities, one component, raw view" << std::endl;
  88. for(std::uint64_t i = 0; i < 1000000L; i++) {
  89. const auto entity = registry.create();
  90. registry.assign<Position>(entity);
  91. }
  92. auto test = [&registry](auto func) {
  93. Timer timer;
  94. registry.view<Position>(entt::raw_t{}).each(func);
  95. timer.elapsed();
  96. };
  97. test([](const auto &) {});
  98. test([](auto &... comp) {
  99. using accumulator_type = int[];
  100. accumulator_type accumulator = { (comp.x = {}, 0)... };
  101. (void)accumulator;
  102. });
  103. }
  104. TEST(Benchmark, IterateSingleComponentRuntime1M) {
  105. entt::DefaultRegistry registry;
  106. std::cout << "Iterating over 1000000 entities, one component, runtime view" << std::endl;
  107. for(std::uint64_t i = 0; i < 1000000L; i++) {
  108. const auto entity = registry.create();
  109. registry.assign<Position>(entity);
  110. }
  111. auto test = [&registry](auto func) {
  112. using component_type = typename entt::DefaultRegistry::component_type;
  113. component_type types[] = { registry.type<Position>() };
  114. Timer timer;
  115. registry.view(std::begin(types), std::end(types)).each(func);
  116. timer.elapsed();
  117. };
  118. test([](auto) {});
  119. test([&registry](auto entity) {
  120. registry.get<Position>(entity).x = {};
  121. });
  122. }
  123. TEST(Benchmark, IterateTwoComponents1M) {
  124. entt::DefaultRegistry registry;
  125. std::cout << "Iterating over 1000000 entities, two components" << std::endl;
  126. for(std::uint64_t i = 0; i < 1000000L; i++) {
  127. const auto entity = registry.create();
  128. registry.assign<Position>(entity);
  129. registry.assign<Velocity>(entity);
  130. }
  131. auto test = [&registry](auto func) {
  132. Timer timer;
  133. registry.view<Position, Velocity>().each(func);
  134. timer.elapsed();
  135. };
  136. test([](auto, const auto &...) {});
  137. test([](auto, auto &... comp) {
  138. using accumulator_type = int[];
  139. accumulator_type accumulator = { (comp.x = {}, 0)... };
  140. (void)accumulator;
  141. });
  142. }
  143. TEST(Benchmark, IterateTwoComponents1MHalf) {
  144. entt::DefaultRegistry registry;
  145. std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components" << std::endl;
  146. for(std::uint64_t i = 0; i < 1000000L; i++) {
  147. const auto entity = registry.create();
  148. registry.assign<Velocity>(entity);
  149. if(i % 2) {
  150. registry.assign<Position>(entity);
  151. }
  152. }
  153. auto test = [&registry](auto func) {
  154. Timer timer;
  155. registry.view<Position, Velocity>().each(func);
  156. timer.elapsed();
  157. };
  158. test([](auto, const auto &...) {});
  159. test([](auto, auto &... comp) {
  160. using accumulator_type = int[];
  161. accumulator_type accumulator = { (comp.x = {}, 0)... };
  162. (void)accumulator;
  163. });
  164. }
  165. TEST(Benchmark, IterateTwoComponents1MOne) {
  166. entt::DefaultRegistry registry;
  167. std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components" << std::endl;
  168. for(std::uint64_t i = 0; i < 1000000L; i++) {
  169. const auto entity = registry.create();
  170. registry.assign<Velocity>(entity);
  171. if(i == 5000000L) {
  172. registry.assign<Position>(entity);
  173. }
  174. }
  175. auto test = [&registry](auto func) {
  176. Timer timer;
  177. registry.view<Position, Velocity>().each(func);
  178. timer.elapsed();
  179. };
  180. test([](auto, const auto &...) {});
  181. test([](auto, auto &... comp) {
  182. using accumulator_type = int[];
  183. accumulator_type accumulator = { (comp.x = {}, 0)... };
  184. (void)accumulator;
  185. });
  186. }
  187. TEST(Benchmark, IterateTwoComponentsPersistent1M) {
  188. entt::DefaultRegistry registry;
  189. registry.prepare<Position, Velocity>();
  190. std::cout << "Iterating over 1000000 entities, two components, persistent view" << std::endl;
  191. for(std::uint64_t i = 0; i < 1000000L; i++) {
  192. const auto entity = registry.create();
  193. registry.assign<Position>(entity);
  194. registry.assign<Velocity>(entity);
  195. }
  196. auto test = [&registry](auto func) {
  197. Timer timer;
  198. registry.view<Position, Velocity>(entt::persistent_t{}).each(func);
  199. timer.elapsed();
  200. };
  201. test([](auto, const auto &...) {});
  202. test([](auto, auto &... comp) {
  203. using accumulator_type = int[];
  204. accumulator_type accumulator = { (comp.x = {}, 0)... };
  205. (void)accumulator;
  206. });
  207. }
  208. TEST(Benchmark, IterateTwoComponentsRuntime1M) {
  209. entt::DefaultRegistry registry;
  210. registry.prepare<Position, Velocity>();
  211. std::cout << "Iterating over 1000000 entities, two components, runtime view" << std::endl;
  212. for(std::uint64_t i = 0; i < 1000000L; i++) {
  213. const auto entity = registry.create();
  214. registry.assign<Position>(entity);
  215. registry.assign<Velocity>(entity);
  216. }
  217. auto test = [&registry](auto func) {
  218. using component_type = typename entt::DefaultRegistry::component_type;
  219. component_type types[] = { registry.type<Position>(), registry.type<Velocity>() };
  220. Timer timer;
  221. registry.view(std::begin(types), std::end(types)).each(func);
  222. timer.elapsed();
  223. };
  224. test([](auto) {});
  225. test([&registry](auto entity) {
  226. registry.get<Position>(entity).x = {};
  227. registry.get<Velocity>(entity).x = {};
  228. });
  229. }
  230. TEST(Benchmark, IterateTwoComponentsRuntime1MHalf) {
  231. entt::DefaultRegistry registry;
  232. std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components, runtime view" << std::endl;
  233. for(std::uint64_t i = 0; i < 1000000L; i++) {
  234. const auto entity = registry.create();
  235. registry.assign<Velocity>(entity);
  236. if(i % 2) {
  237. registry.assign<Position>(entity);
  238. }
  239. }
  240. auto test = [&registry](auto func) {
  241. using component_type = typename entt::DefaultRegistry::component_type;
  242. component_type types[] = { registry.type<Position>(), registry.type<Velocity>() };
  243. Timer timer;
  244. registry.view(std::begin(types), std::end(types)).each(func);
  245. timer.elapsed();
  246. };
  247. test([](auto) {});
  248. test([&registry](auto entity) {
  249. registry.get<Position>(entity).x = {};
  250. registry.get<Velocity>(entity).x = {};
  251. });
  252. }
  253. TEST(Benchmark, IterateTwoComponentsRuntime1MOne) {
  254. entt::DefaultRegistry registry;
  255. std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components, runtime view" << std::endl;
  256. for(std::uint64_t i = 0; i < 1000000L; i++) {
  257. const auto entity = registry.create();
  258. registry.assign<Velocity>(entity);
  259. if(i == 5000000L) {
  260. registry.assign<Position>(entity);
  261. }
  262. }
  263. auto test = [&registry](auto func) {
  264. using component_type = typename entt::DefaultRegistry::component_type;
  265. component_type types[] = { registry.type<Position>(), registry.type<Velocity>() };
  266. Timer timer;
  267. registry.view(std::begin(types), std::end(types)).each(func);
  268. timer.elapsed();
  269. };
  270. test([](auto) {});
  271. test([&registry](auto entity) {
  272. registry.get<Position>(entity).x = {};
  273. registry.get<Velocity>(entity).x = {};
  274. });
  275. }
  276. TEST(Benchmark, IterateFiveComponents1M) {
  277. entt::DefaultRegistry registry;
  278. std::cout << "Iterating over 1000000 entities, five components" << std::endl;
  279. for(std::uint64_t i = 0; i < 1000000L; i++) {
  280. const auto entity = registry.create();
  281. registry.assign<Position>(entity);
  282. registry.assign<Velocity>(entity);
  283. registry.assign<Comp<1>>(entity);
  284. registry.assign<Comp<2>>(entity);
  285. registry.assign<Comp<3>>(entity);
  286. }
  287. auto test = [&registry](auto func) {
  288. Timer timer;
  289. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
  290. timer.elapsed();
  291. };
  292. test([](auto, const auto &...) {});
  293. test([](auto, auto &... comp) {
  294. using accumulator_type = int[];
  295. accumulator_type accumulator = { (comp.x = {}, 0)... };
  296. (void)accumulator;
  297. });
  298. }
  299. TEST(Benchmark, IterateFiveComponents1MHalf) {
  300. entt::DefaultRegistry registry;
  301. std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components" << std::endl;
  302. for(std::uint64_t i = 0; i < 1000000L; i++) {
  303. const auto entity = registry.create();
  304. registry.assign<Velocity>(entity);
  305. registry.assign<Comp<1>>(entity);
  306. registry.assign<Comp<2>>(entity);
  307. registry.assign<Comp<3>>(entity);
  308. if(i % 2) {
  309. registry.assign<Position>(entity);
  310. }
  311. }
  312. auto test = [&registry](auto func) {
  313. Timer timer;
  314. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
  315. timer.elapsed();
  316. };
  317. test([](auto, const auto &...) {});
  318. test([](auto, auto &... comp) {
  319. using accumulator_type = int[];
  320. accumulator_type accumulator = { (comp.x = {}, 0)... };
  321. (void)accumulator;
  322. });
  323. }
  324. TEST(Benchmark, IterateFiveComponents1MOne) {
  325. entt::DefaultRegistry registry;
  326. std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components" << std::endl;
  327. for(std::uint64_t i = 0; i < 1000000L; i++) {
  328. const auto entity = registry.create();
  329. registry.assign<Velocity>(entity);
  330. registry.assign<Comp<1>>(entity);
  331. registry.assign<Comp<2>>(entity);
  332. registry.assign<Comp<3>>(entity);
  333. if(i == 5000000L) {
  334. registry.assign<Position>(entity);
  335. }
  336. }
  337. auto test = [&registry](auto func) {
  338. Timer timer;
  339. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
  340. timer.elapsed();
  341. };
  342. test([](auto, const auto &...) {});
  343. test([](auto, auto &... comp) {
  344. using accumulator_type = int[];
  345. accumulator_type accumulator = { (comp.x = {}, 0)... };
  346. (void)accumulator;
  347. });
  348. }
  349. TEST(Benchmark, IterateFiveComponentsPersistent1M) {
  350. entt::DefaultRegistry registry;
  351. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  352. std::cout << "Iterating over 1000000 entities, five components, persistent view" << std::endl;
  353. for(std::uint64_t i = 0; i < 1000000L; i++) {
  354. const auto entity = registry.create();
  355. registry.assign<Position>(entity);
  356. registry.assign<Velocity>(entity);
  357. registry.assign<Comp<1>>(entity);
  358. registry.assign<Comp<2>>(entity);
  359. registry.assign<Comp<3>>(entity);
  360. }
  361. auto test = [&registry](auto func) {
  362. Timer timer;
  363. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>(entt::persistent_t{}).each(func);
  364. timer.elapsed();
  365. };
  366. test([](auto, const auto &...) {});
  367. test([](auto, auto &... comp) {
  368. using accumulator_type = int[];
  369. accumulator_type accumulator = { (comp.x = {}, 0)... };
  370. (void)accumulator;
  371. });
  372. }
  373. TEST(Benchmark, IterateFiveComponentsRuntime1M) {
  374. entt::DefaultRegistry registry;
  375. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
  376. std::cout << "Iterating over 1000000 entities, five components, runtime view" << std::endl;
  377. for(std::uint64_t i = 0; i < 1000000L; i++) {
  378. const auto entity = registry.create();
  379. registry.assign<Position>(entity);
  380. registry.assign<Velocity>(entity);
  381. registry.assign<Comp<1>>(entity);
  382. registry.assign<Comp<2>>(entity);
  383. registry.assign<Comp<3>>(entity);
  384. }
  385. auto test = [&registry](auto func) {
  386. using component_type = typename entt::DefaultRegistry::component_type;
  387. component_type types[] = {
  388. registry.type<Position>(),
  389. registry.type<Velocity>(),
  390. registry.type<Comp<1>>(),
  391. registry.type<Comp<2>>(),
  392. registry.type<Comp<3>>()
  393. };
  394. Timer timer;
  395. registry.view(std::begin(types), std::end(types)).each(func);
  396. timer.elapsed();
  397. };
  398. test([](auto) {});
  399. test([&registry](auto entity) {
  400. registry.get<Position>(entity).x = {};
  401. registry.get<Velocity>(entity).x = {};
  402. registry.get<Comp<1>>(entity).x = {};
  403. registry.get<Comp<2>>(entity).x = {};
  404. registry.get<Comp<3>>(entity).x = {};
  405. });
  406. }
  407. TEST(Benchmark, IterateFiveComponentsRuntime1MHalf) {
  408. entt::DefaultRegistry registry;
  409. std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components, runtime view" << std::endl;
  410. for(std::uint64_t i = 0; i < 1000000L; i++) {
  411. const auto entity = registry.create();
  412. registry.assign<Velocity>(entity);
  413. registry.assign<Comp<1>>(entity);
  414. registry.assign<Comp<2>>(entity);
  415. registry.assign<Comp<3>>(entity);
  416. if(i % 2) {
  417. registry.assign<Position>(entity);
  418. }
  419. }
  420. auto test = [&registry](auto func) {
  421. using component_type = typename entt::DefaultRegistry::component_type;
  422. component_type types[] = {
  423. registry.type<Position>(),
  424. registry.type<Velocity>(),
  425. registry.type<Comp<1>>(),
  426. registry.type<Comp<2>>(),
  427. registry.type<Comp<3>>()
  428. };
  429. Timer timer;
  430. registry.view(std::begin(types), std::end(types)).each(func);
  431. timer.elapsed();
  432. };
  433. test([](auto) {});
  434. test([&registry](auto entity) {
  435. registry.get<Position>(entity).x = {};
  436. registry.get<Velocity>(entity).x = {};
  437. registry.get<Comp<1>>(entity).x = {};
  438. registry.get<Comp<2>>(entity).x = {};
  439. registry.get<Comp<3>>(entity).x = {};
  440. });
  441. }
  442. TEST(Benchmark, IterateFiveComponentsRuntime1MOne) {
  443. entt::DefaultRegistry registry;
  444. std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components, runtime view" << std::endl;
  445. for(std::uint64_t i = 0; i < 1000000L; i++) {
  446. const auto entity = registry.create();
  447. registry.assign<Velocity>(entity);
  448. registry.assign<Comp<1>>(entity);
  449. registry.assign<Comp<2>>(entity);
  450. registry.assign<Comp<3>>(entity);
  451. if(i == 5000000L) {
  452. registry.assign<Position>(entity);
  453. }
  454. }
  455. auto test = [&registry](auto func) {
  456. using component_type = typename entt::DefaultRegistry::component_type;
  457. component_type types[] = {
  458. registry.type<Position>(),
  459. registry.type<Velocity>(),
  460. registry.type<Comp<1>>(),
  461. registry.type<Comp<2>>(),
  462. registry.type<Comp<3>>()
  463. };
  464. Timer timer;
  465. registry.view(std::begin(types), std::end(types)).each(func);
  466. timer.elapsed();
  467. };
  468. test([](auto) {});
  469. test([&registry](auto entity) {
  470. registry.get<Position>(entity).x = {};
  471. registry.get<Velocity>(entity).x = {};
  472. registry.get<Comp<1>>(entity).x = {};
  473. registry.get<Comp<2>>(entity).x = {};
  474. registry.get<Comp<3>>(entity).x = {};
  475. });
  476. }
  477. TEST(Benchmark, IterateTenComponents1M) {
  478. entt::DefaultRegistry registry;
  479. std::cout << "Iterating over 1000000 entities, ten components" << std::endl;
  480. for(std::uint64_t i = 0; i < 1000000L; i++) {
  481. const auto entity = registry.create();
  482. registry.assign<Position>(entity);
  483. registry.assign<Velocity>(entity);
  484. registry.assign<Comp<1>>(entity);
  485. registry.assign<Comp<2>>(entity);
  486. registry.assign<Comp<3>>(entity);
  487. registry.assign<Comp<4>>(entity);
  488. registry.assign<Comp<5>>(entity);
  489. registry.assign<Comp<6>>(entity);
  490. registry.assign<Comp<7>>(entity);
  491. registry.assign<Comp<8>>(entity);
  492. }
  493. auto test = [&registry](auto func) {
  494. Timer timer;
  495. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
  496. timer.elapsed();
  497. };
  498. test([](auto, const auto &...) {});
  499. test([](auto, auto &... comp) {
  500. using accumulator_type = int[];
  501. accumulator_type accumulator = { (comp.x = {}, 0)... };
  502. (void)accumulator;
  503. });
  504. }
  505. TEST(Benchmark, IterateTenComponents1MHalf) {
  506. entt::DefaultRegistry registry;
  507. std::cout << "Iterating over 1000000 entities, ten components, half of the entities have all the components" << std::endl;
  508. for(std::uint64_t i = 0; i < 1000000L; i++) {
  509. const auto entity = registry.create();
  510. registry.assign<Velocity>(entity);
  511. registry.assign<Comp<1>>(entity);
  512. registry.assign<Comp<2>>(entity);
  513. registry.assign<Comp<3>>(entity);
  514. registry.assign<Comp<4>>(entity);
  515. registry.assign<Comp<5>>(entity);
  516. registry.assign<Comp<6>>(entity);
  517. registry.assign<Comp<7>>(entity);
  518. registry.assign<Comp<8>>(entity);
  519. if(i % 2) {
  520. registry.assign<Position>(entity);
  521. }
  522. }
  523. auto test = [&registry](auto func) {
  524. Timer timer;
  525. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
  526. timer.elapsed();
  527. };
  528. test([](auto, auto &...) {});
  529. test([](auto, auto &... comp) {
  530. using accumulator_type = int[];
  531. accumulator_type accumulator = { (comp.x = {}, 0)... };
  532. (void)accumulator;
  533. });
  534. }
  535. TEST(Benchmark, IterateTenComponents1MOne) {
  536. entt::DefaultRegistry registry;
  537. std::cout << "Iterating over 1000000 entities, ten components, only one entity has all the components" << std::endl;
  538. for(std::uint64_t i = 0; i < 1000000L; i++) {
  539. const auto entity = registry.create();
  540. registry.assign<Velocity>(entity);
  541. registry.assign<Comp<1>>(entity);
  542. registry.assign<Comp<2>>(entity);
  543. registry.assign<Comp<3>>(entity);
  544. registry.assign<Comp<4>>(entity);
  545. registry.assign<Comp<5>>(entity);
  546. registry.assign<Comp<6>>(entity);
  547. registry.assign<Comp<7>>(entity);
  548. registry.assign<Comp<8>>(entity);
  549. if(i == 5000000L) {
  550. registry.assign<Position>(entity);
  551. }
  552. }
  553. auto test = [&registry](auto func) {
  554. Timer timer;
  555. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
  556. timer.elapsed();
  557. };
  558. test([](auto, const auto &...) {});
  559. test([](auto, auto &... comp) {
  560. using accumulator_type = int[];
  561. accumulator_type accumulator = { (comp.x = {}, 0)... };
  562. (void)accumulator;
  563. });
  564. }
  565. TEST(Benchmark, IterateTenComponentsPersistent1M) {
  566. entt::DefaultRegistry registry;
  567. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  568. std::cout << "Iterating over 1000000 entities, ten components, persistent view" << std::endl;
  569. for(std::uint64_t i = 0; i < 1000000L; i++) {
  570. const auto entity = registry.create();
  571. registry.assign<Position>(entity);
  572. registry.assign<Velocity>(entity);
  573. registry.assign<Comp<1>>(entity);
  574. registry.assign<Comp<2>>(entity);
  575. registry.assign<Comp<3>>(entity);
  576. registry.assign<Comp<4>>(entity);
  577. registry.assign<Comp<5>>(entity);
  578. registry.assign<Comp<6>>(entity);
  579. registry.assign<Comp<7>>(entity);
  580. registry.assign<Comp<8>>(entity);
  581. }
  582. auto test = [&registry](auto func) {
  583. Timer timer;
  584. registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>(entt::persistent_t{}).each(func);
  585. timer.elapsed();
  586. };
  587. test([](auto, const auto &...) {});
  588. test([](auto, auto &... comp) {
  589. using accumulator_type = int[];
  590. accumulator_type accumulator = { (comp.x = {}, 0)... };
  591. (void)accumulator;
  592. });
  593. }
  594. TEST(Benchmark, IterateTenComponentsRuntime1M) {
  595. entt::DefaultRegistry registry;
  596. registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
  597. std::cout << "Iterating over 1000000 entities, ten components, runtime view" << std::endl;
  598. for(std::uint64_t i = 0; i < 1000000L; i++) {
  599. const auto entity = registry.create();
  600. registry.assign<Position>(entity);
  601. registry.assign<Velocity>(entity);
  602. registry.assign<Comp<1>>(entity);
  603. registry.assign<Comp<2>>(entity);
  604. registry.assign<Comp<3>>(entity);
  605. registry.assign<Comp<4>>(entity);
  606. registry.assign<Comp<5>>(entity);
  607. registry.assign<Comp<6>>(entity);
  608. registry.assign<Comp<7>>(entity);
  609. registry.assign<Comp<8>>(entity);
  610. }
  611. auto test = [&registry](auto func) {
  612. using component_type = typename entt::DefaultRegistry::component_type;
  613. component_type types[] = {
  614. registry.type<Position>(),
  615. registry.type<Velocity>(),
  616. registry.type<Comp<1>>(),
  617. registry.type<Comp<2>>(),
  618. registry.type<Comp<3>>(),
  619. registry.type<Comp<4>>(),
  620. registry.type<Comp<5>>(),
  621. registry.type<Comp<6>>(),
  622. registry.type<Comp<7>>(),
  623. registry.type<Comp<8>>()
  624. };
  625. Timer timer;
  626. registry.view(std::begin(types), std::end(types)).each(func);
  627. timer.elapsed();
  628. };
  629. test([](auto) {});
  630. test([&registry](auto entity) {
  631. registry.get<Position>(entity).x = {};
  632. registry.get<Velocity>(entity).x = {};
  633. registry.get<Comp<1>>(entity).x = {};
  634. registry.get<Comp<2>>(entity).x = {};
  635. registry.get<Comp<3>>(entity).x = {};
  636. registry.get<Comp<4>>(entity).x = {};
  637. registry.get<Comp<5>>(entity).x = {};
  638. registry.get<Comp<6>>(entity).x = {};
  639. registry.get<Comp<7>>(entity).x = {};
  640. registry.get<Comp<8>>(entity).x = {};
  641. });
  642. }
  643. TEST(Benchmark, IterateTenComponentsRuntime1MHalf) {
  644. entt::DefaultRegistry registry;
  645. std::cout << "Iterating over 1000000 entities, ten components, half of the entities have all the components, runtime view" << std::endl;
  646. for(std::uint64_t i = 0; i < 1000000L; i++) {
  647. const auto entity = registry.create();
  648. registry.assign<Velocity>(entity);
  649. registry.assign<Comp<1>>(entity);
  650. registry.assign<Comp<2>>(entity);
  651. registry.assign<Comp<3>>(entity);
  652. registry.assign<Comp<4>>(entity);
  653. registry.assign<Comp<5>>(entity);
  654. registry.assign<Comp<6>>(entity);
  655. registry.assign<Comp<7>>(entity);
  656. registry.assign<Comp<8>>(entity);
  657. if(i % 2) {
  658. registry.assign<Position>(entity);
  659. }
  660. }
  661. auto test = [&registry](auto func) {
  662. using component_type = typename entt::DefaultRegistry::component_type;
  663. component_type types[] = {
  664. registry.type<Position>(),
  665. registry.type<Velocity>(),
  666. registry.type<Comp<1>>(),
  667. registry.type<Comp<2>>(),
  668. registry.type<Comp<3>>(),
  669. registry.type<Comp<4>>(),
  670. registry.type<Comp<5>>(),
  671. registry.type<Comp<6>>(),
  672. registry.type<Comp<7>>(),
  673. registry.type<Comp<8>>()
  674. };
  675. Timer timer;
  676. registry.view(std::begin(types), std::end(types)).each(func);
  677. timer.elapsed();
  678. };
  679. test([](auto) {});
  680. test([&registry](auto entity) {
  681. registry.get<Position>(entity).x = {};
  682. registry.get<Velocity>(entity).x = {};
  683. registry.get<Comp<1>>(entity).x = {};
  684. registry.get<Comp<2>>(entity).x = {};
  685. registry.get<Comp<3>>(entity).x = {};
  686. registry.get<Comp<4>>(entity).x = {};
  687. registry.get<Comp<5>>(entity).x = {};
  688. registry.get<Comp<6>>(entity).x = {};
  689. registry.get<Comp<7>>(entity).x = {};
  690. registry.get<Comp<8>>(entity).x = {};
  691. });
  692. }
  693. TEST(Benchmark, IterateTenComponentsRuntime1MOne) {
  694. entt::DefaultRegistry registry;
  695. std::cout << "Iterating over 1000000 entities, ten components, only one entity has all the components, runtime view" << std::endl;
  696. for(std::uint64_t i = 0; i < 1000000L; i++) {
  697. const auto entity = registry.create();
  698. registry.assign<Velocity>(entity);
  699. registry.assign<Comp<1>>(entity);
  700. registry.assign<Comp<2>>(entity);
  701. registry.assign<Comp<3>>(entity);
  702. registry.assign<Comp<4>>(entity);
  703. registry.assign<Comp<5>>(entity);
  704. registry.assign<Comp<6>>(entity);
  705. registry.assign<Comp<7>>(entity);
  706. registry.assign<Comp<8>>(entity);
  707. if(i == 5000000L) {
  708. registry.assign<Position>(entity);
  709. }
  710. }
  711. auto test = [&registry](auto func) {
  712. using component_type = typename entt::DefaultRegistry::component_type;
  713. component_type types[] = {
  714. registry.type<Position>(),
  715. registry.type<Velocity>(),
  716. registry.type<Comp<1>>(),
  717. registry.type<Comp<2>>(),
  718. registry.type<Comp<3>>(),
  719. registry.type<Comp<4>>(),
  720. registry.type<Comp<5>>(),
  721. registry.type<Comp<6>>(),
  722. registry.type<Comp<7>>(),
  723. registry.type<Comp<8>>()
  724. };
  725. Timer timer;
  726. registry.view(std::begin(types), std::end(types)).each(func);
  727. timer.elapsed();
  728. };
  729. test([](auto) {});
  730. test([&registry](auto entity) {
  731. registry.get<Position>(entity).x = {};
  732. registry.get<Velocity>(entity).x = {};
  733. registry.get<Comp<1>>(entity).x = {};
  734. registry.get<Comp<2>>(entity).x = {};
  735. registry.get<Comp<3>>(entity).x = {};
  736. registry.get<Comp<4>>(entity).x = {};
  737. registry.get<Comp<5>>(entity).x = {};
  738. registry.get<Comp<6>>(entity).x = {};
  739. registry.get<Comp<7>>(entity).x = {};
  740. registry.get<Comp<8>>(entity).x = {};
  741. });
  742. }
  743. TEST(Benchmark, SortSingle) {
  744. entt::DefaultRegistry registry;
  745. std::cout << "Sort 150000 entities, one component" << std::endl;
  746. for(std::uint64_t i = 0; i < 150000L; i++) {
  747. const auto entity = registry.create();
  748. registry.assign<Position>(entity, i, i);
  749. }
  750. Timer timer;
  751. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  752. return lhs.x < rhs.x && lhs.y < rhs.y;
  753. });
  754. timer.elapsed();
  755. }
  756. TEST(Benchmark, SortMulti) {
  757. entt::DefaultRegistry registry;
  758. std::cout << "Sort 150000 entities, two components" << std::endl;
  759. for(std::uint64_t i = 0; i < 150000L; i++) {
  760. const auto entity = registry.create();
  761. registry.assign<Position>(entity, i, i);
  762. registry.assign<Velocity>(entity, i, i);
  763. }
  764. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  765. return lhs.x < rhs.x && lhs.y < rhs.y;
  766. });
  767. Timer timer;
  768. registry.sort<Velocity, Position>();
  769. timer.elapsed();
  770. }
  771. TEST(Benchmark, AlmostSortedStdSort) {
  772. entt::DefaultRegistry registry;
  773. entt::DefaultRegistry::entity_type entities[3];
  774. std::cout << "Sort 150000 entities, almost sorted, std::sort" << std::endl;
  775. for(std::uint64_t i = 0; i < 150000L; i++) {
  776. const auto entity = registry.create();
  777. registry.assign<Position>(entity, i, i);
  778. if(!(i % 50000)) {
  779. entities[i / 50000] = entity;
  780. }
  781. }
  782. for(std::uint64_t i = 0; i < 3; ++i) {
  783. registry.destroy(entities[i]);
  784. const auto entity = registry.create();
  785. registry.assign<Position>(entity, 50000 * i, 50000 * i);
  786. }
  787. Timer timer;
  788. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  789. return lhs.x > rhs.x && lhs.y > rhs.y;
  790. });
  791. timer.elapsed();
  792. }
  793. TEST(Benchmark, AlmostSortedInsertionSort) {
  794. entt::DefaultRegistry registry;
  795. entt::DefaultRegistry::entity_type entities[3];
  796. std::cout << "Sort 150000 entities, almost sorted, insertion sort" << std::endl;
  797. for(std::uint64_t i = 0; i < 150000L; i++) {
  798. const auto entity = registry.create();
  799. registry.assign<Position>(entity, i, i);
  800. if(!(i % 50000)) {
  801. entities[i / 50000] = entity;
  802. }
  803. }
  804. for(std::uint64_t i = 0; i < 3; ++i) {
  805. registry.destroy(entities[i]);
  806. const auto entity = registry.create();
  807. registry.assign<Position>(entity, 50000 * i, 50000 * i);
  808. }
  809. Timer timer;
  810. registry.sort<Position>([](const auto &lhs, const auto &rhs) {
  811. return lhs.x > rhs.x && lhs.y > rhs.y;
  812. }, entt::InsertionSort{});
  813. timer.elapsed();
  814. }