benchmark.cpp 29 KB

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