benchmark.cpp 29 KB

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