benchmark.cpp 28 KB

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