benchmark.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  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::entity> 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, ConstructManyAndAssignComponents) {
  45. entt::registry registry;
  46. std::vector<entt::entity> entities(1000000);
  47. std::cout << "Constructing 1000000 entities at once and assign components" << std::endl;
  48. timer timer;
  49. registry.create(entities.begin(), entities.end());
  50. for(const auto entity: entities) {
  51. registry.assign<position>(entity);
  52. registry.assign<velocity>(entity);
  53. }
  54. timer.elapsed();
  55. }
  56. TEST(Benchmark, ConstructManyWithComponents) {
  57. entt::registry registry;
  58. std::vector<entt::entity> entities(1000000);
  59. std::cout << "Constructing 1000000 entities at once with components" << std::endl;
  60. timer timer;
  61. registry.create<position, velocity>(entities.begin(), entities.end());
  62. timer.elapsed();
  63. }
  64. TEST(Benchmark, Destroy) {
  65. entt::registry registry;
  66. std::cout << "Destroying 1000000 entities" << std::endl;
  67. for(std::uint64_t i = 0; i < 1000000L; i++) {
  68. registry.create();
  69. }
  70. timer timer;
  71. registry.each([&registry](auto entity) {
  72. registry.destroy(entity);
  73. });
  74. timer.elapsed();
  75. }
  76. TEST(Benchmark, IterateCreateDeleteSingleComponent) {
  77. entt::registry registry;
  78. std::cout << "Looping 10000 times creating and deleting a random number of entities" << std::endl;
  79. timer timer;
  80. auto view = registry.view<position>();
  81. for(int i = 0; i < 10000; i++) {
  82. for(int j = 0; j < 10000; j++) {
  83. const auto entity = registry.create();
  84. registry.assign<position>(entity);
  85. }
  86. for(auto entity: view) {
  87. if(rand() % 2 == 0) {
  88. registry.destroy(entity);
  89. }
  90. }
  91. }
  92. timer.elapsed();
  93. }
  94. TEST(Benchmark, IterateSingleComponent1M) {
  95. entt::registry registry;
  96. std::cout << "Iterating over 1000000 entities, one component" << std::endl;
  97. for(std::uint64_t i = 0; i < 1000000L; i++) {
  98. const auto entity = registry.create();
  99. registry.assign<position>(entity);
  100. }
  101. auto test = [&registry](auto func) {
  102. timer timer;
  103. registry.view<position>().each(func);
  104. timer.elapsed();
  105. };
  106. test([](const auto &...) {});
  107. test([](auto &... comp) {
  108. ((comp.x = {}), ...);
  109. });
  110. }
  111. TEST(Benchmark, IterateSingleComponentRuntime1M) {
  112. entt::registry registry;
  113. std::cout << "Iterating over 1000000 entities, one component, runtime view" << std::endl;
  114. for(std::uint64_t i = 0; i < 1000000L; i++) {
  115. const auto entity = registry.create();
  116. registry.assign<position>(entity);
  117. }
  118. auto test = [&registry](auto func) {
  119. using component_type = typename entt::registry::component_type;
  120. component_type types[] = { registry.type<position>() };
  121. timer timer;
  122. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  123. timer.elapsed();
  124. };
  125. test([](auto) {});
  126. test([&registry](auto entity) {
  127. registry.get<position>(entity).x = {};
  128. });
  129. }
  130. TEST(Benchmark, IterateTwoComponents1M) {
  131. entt::registry registry;
  132. std::cout << "Iterating over 1000000 entities, two components" << std::endl;
  133. for(std::uint64_t i = 0; i < 1000000L; i++) {
  134. const auto entity = registry.create();
  135. registry.assign<position>(entity);
  136. registry.assign<velocity>(entity);
  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, IterateTwoComponents1MHalf) {
  149. entt::registry registry;
  150. std::cout << "Iterating over 1000000 entities, two components, half of the entities have 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 % 2) {
  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, IterateTwoComponents1MOne) {
  169. entt::registry registry;
  170. std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components" << std::endl;
  171. for(std::uint64_t i = 0; i < 1000000L; i++) {
  172. const auto entity = registry.create();
  173. registry.assign<velocity>(entity);
  174. if(i == 5000000L) {
  175. registry.assign<position>(entity);
  176. }
  177. }
  178. auto test = [&registry](auto func) {
  179. timer timer;
  180. registry.view<position, velocity>().each(func);
  181. timer.elapsed();
  182. };
  183. test([](const auto &...) {});
  184. test([](auto &... comp) {
  185. ((comp.x = {}), ...);
  186. });
  187. }
  188. TEST(Benchmark, IterateTwoComponentsNonOwningGroup1M) {
  189. entt::registry registry;
  190. registry.group<>(entt::get<position, velocity>);
  191. std::cout << "Iterating over 1000000 entities, two components, non owning group" << std::endl;
  192. for(std::uint64_t i = 0; i < 1000000L; i++) {
  193. const auto entity = registry.create();
  194. registry.assign<position>(entity);
  195. registry.assign<velocity>(entity);
  196. }
  197. auto test = [&registry](auto func) {
  198. timer timer;
  199. registry.group<>(entt::get<position, velocity>).each(func);
  200. timer.elapsed();
  201. };
  202. test([](const auto &...) {});
  203. test([](auto &... comp) {
  204. ((comp.x = {}), ...);
  205. });
  206. }
  207. TEST(Benchmark, IterateTwoComponentsFullOwningGroup1M) {
  208. entt::registry registry;
  209. registry.group<position, velocity>();
  210. std::cout << "Iterating over 1000000 entities, two components, full owning group" << std::endl;
  211. for(std::uint64_t i = 0; i < 1000000L; i++) {
  212. const auto entity = registry.create();
  213. registry.assign<position>(entity);
  214. registry.assign<velocity>(entity);
  215. }
  216. auto test = [&registry](auto func) {
  217. timer timer;
  218. registry.group<position, velocity>().each(func);
  219. timer.elapsed();
  220. };
  221. test([](const auto &...) {});
  222. test([](auto &... comp) {
  223. ((comp.x = {}), ...);
  224. });
  225. }
  226. TEST(Benchmark, IterateTwoComponentsPartialOwningGroup1M) {
  227. entt::registry registry;
  228. registry.group<position>(entt::get<velocity>);
  229. std::cout << "Iterating over 1000000 entities, two components, partial owning group" << std::endl;
  230. for(std::uint64_t i = 0; i < 1000000L; i++) {
  231. const auto entity = registry.create();
  232. registry.assign<position>(entity);
  233. registry.assign<velocity>(entity);
  234. }
  235. auto test = [&registry](auto func) {
  236. timer timer;
  237. registry.group<position>(entt::get<velocity>).each(func);
  238. timer.elapsed();
  239. };
  240. test([](const auto &...) {});
  241. test([](auto &... comp) {
  242. ((comp.x = {}), ...);
  243. });
  244. }
  245. TEST(Benchmark, IterateTwoComponentsRuntime1M) {
  246. entt::registry registry;
  247. std::cout << "Iterating over 1000000 entities, two components, runtime view" << std::endl;
  248. for(std::uint64_t i = 0; i < 1000000L; i++) {
  249. const auto entity = registry.create();
  250. registry.assign<position>(entity);
  251. registry.assign<velocity>(entity);
  252. }
  253. auto test = [&registry](auto func) {
  254. using component_type = typename entt::registry::component_type;
  255. component_type types[] = { registry.type<position>(), registry.type<velocity>() };
  256. timer timer;
  257. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  258. timer.elapsed();
  259. };
  260. test([](auto) {});
  261. test([&registry](auto entity) {
  262. registry.get<position>(entity).x = {};
  263. registry.get<velocity>(entity).x = {};
  264. });
  265. }
  266. TEST(Benchmark, IterateTwoComponentsRuntime1MHalf) {
  267. entt::registry registry;
  268. std::cout << "Iterating over 1000000 entities, two components, half of the entities have all the components, runtime view" << std::endl;
  269. for(std::uint64_t i = 0; i < 1000000L; i++) {
  270. const auto entity = registry.create();
  271. registry.assign<velocity>(entity);
  272. if(i % 2) {
  273. registry.assign<position>(entity);
  274. }
  275. }
  276. auto test = [&registry](auto func) {
  277. using component_type = typename entt::registry::component_type;
  278. component_type types[] = { registry.type<position>(), registry.type<velocity>() };
  279. timer timer;
  280. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  281. timer.elapsed();
  282. };
  283. test([](auto) {});
  284. test([&registry](auto entity) {
  285. registry.get<position>(entity).x = {};
  286. registry.get<velocity>(entity).x = {};
  287. });
  288. }
  289. TEST(Benchmark, IterateTwoComponentsRuntime1MOne) {
  290. entt::registry registry;
  291. std::cout << "Iterating over 1000000 entities, two components, only one entity has all the components, runtime view" << std::endl;
  292. for(std::uint64_t i = 0; i < 1000000L; i++) {
  293. const auto entity = registry.create();
  294. registry.assign<velocity>(entity);
  295. if(i == 5000000L) {
  296. registry.assign<position>(entity);
  297. }
  298. }
  299. auto test = [&registry](auto func) {
  300. using component_type = typename entt::registry::component_type;
  301. component_type types[] = { registry.type<position>(), registry.type<velocity>() };
  302. timer timer;
  303. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  304. timer.elapsed();
  305. };
  306. test([](auto) {});
  307. test([&registry](auto entity) {
  308. registry.get<position>(entity).x = {};
  309. registry.get<velocity>(entity).x = {};
  310. });
  311. }
  312. TEST(Benchmark, IterateThreeComponents1M) {
  313. entt::registry registry;
  314. std::cout << "Iterating over 1000000 entities, three components" << std::endl;
  315. for(std::uint64_t i = 0; i < 1000000L; i++) {
  316. const auto entity = registry.create();
  317. registry.assign<position>(entity);
  318. registry.assign<velocity>(entity);
  319. registry.assign<comp<0>>(entity);
  320. }
  321. auto test = [&registry](auto func) {
  322. timer timer;
  323. registry.view<position, velocity, comp<0>>().each(func);
  324. timer.elapsed();
  325. };
  326. test([](const auto &...) {});
  327. test([](auto &... comp) {
  328. ((comp.x = {}), ...);
  329. });
  330. }
  331. TEST(Benchmark, IterateThreeComponents1MHalf) {
  332. entt::registry registry;
  333. std::cout << "Iterating over 1000000 entities, three components, half of the entities have all the components" << std::endl;
  334. for(std::uint64_t i = 0; i < 1000000L; i++) {
  335. const auto entity = registry.create();
  336. registry.assign<velocity>(entity);
  337. registry.assign<comp<0>>(entity);
  338. if(i % 2) {
  339. registry.assign<position>(entity);
  340. }
  341. }
  342. auto test = [&registry](auto func) {
  343. timer timer;
  344. registry.view<position, velocity, comp<0>>().each(func);
  345. timer.elapsed();
  346. };
  347. test([](const auto &...) {});
  348. test([](auto &... comp) {
  349. ((comp.x = {}), ...);
  350. });
  351. }
  352. TEST(Benchmark, IterateThreeComponents1MOne) {
  353. entt::registry registry;
  354. std::cout << "Iterating over 1000000 entities, three components, only one entity has all the components" << std::endl;
  355. for(std::uint64_t i = 0; i < 1000000L; i++) {
  356. const auto entity = registry.create();
  357. registry.assign<velocity>(entity);
  358. registry.assign<comp<0>>(entity);
  359. if(i == 5000000L) {
  360. registry.assign<position>(entity);
  361. }
  362. }
  363. auto test = [&registry](auto func) {
  364. timer timer;
  365. registry.view<position, velocity, comp<0>>().each(func);
  366. timer.elapsed();
  367. };
  368. test([](const auto &...) {});
  369. test([](auto &... comp) {
  370. ((comp.x = {}), ...);
  371. });
  372. }
  373. TEST(Benchmark, IterateThreeComponentsNonOwningGroup1M) {
  374. entt::registry registry;
  375. registry.group<>(entt::get<position, velocity, comp<0>>);
  376. std::cout << "Iterating over 1000000 entities, three components, non owning group" << std::endl;
  377. for(std::uint64_t i = 0; i < 1000000L; i++) {
  378. const auto entity = registry.create();
  379. registry.assign<position>(entity);
  380. registry.assign<velocity>(entity);
  381. registry.assign<comp<0>>(entity);
  382. }
  383. auto test = [&registry](auto func) {
  384. timer timer;
  385. registry.group<>(entt::get<position, velocity, comp<0>>).each(func);
  386. timer.elapsed();
  387. };
  388. test([](const auto &...) {});
  389. test([](auto &... comp) {
  390. ((comp.x = {}), ...);
  391. });
  392. }
  393. TEST(Benchmark, IterateThreeComponentsFullOwningGroup1M) {
  394. entt::registry registry;
  395. registry.group<position, velocity, comp<0>>();
  396. std::cout << "Iterating over 1000000 entities, three components, full owning group" << std::endl;
  397. for(std::uint64_t i = 0; i < 1000000L; i++) {
  398. const auto entity = registry.create();
  399. registry.assign<position>(entity);
  400. registry.assign<velocity>(entity);
  401. registry.assign<comp<0>>(entity);
  402. }
  403. auto test = [&registry](auto func) {
  404. timer timer;
  405. registry.group<position, velocity, comp<0>>().each(func);
  406. timer.elapsed();
  407. };
  408. test([](const auto &...) {});
  409. test([](auto &... comp) {
  410. ((comp.x = {}), ...);
  411. });
  412. }
  413. TEST(Benchmark, IterateThreeComponentsPartialOwningGroup1M) {
  414. entt::registry registry;
  415. registry.group<position, velocity>(entt::get<comp<0>>);
  416. std::cout << "Iterating over 1000000 entities, three components, partial owning group" << std::endl;
  417. for(std::uint64_t i = 0; i < 1000000L; i++) {
  418. const auto entity = registry.create();
  419. registry.assign<position>(entity);
  420. registry.assign<velocity>(entity);
  421. registry.assign<comp<0>>(entity);
  422. }
  423. auto test = [&registry](auto func) {
  424. timer timer;
  425. registry.group<position, velocity>(entt::get<comp<0>>).each(func);
  426. timer.elapsed();
  427. };
  428. test([](const auto &...) {});
  429. test([](auto &... comp) {
  430. ((comp.x = {}), ...);
  431. });
  432. }
  433. TEST(Benchmark, IterateThreeComponentsRuntime1M) {
  434. entt::registry registry;
  435. std::cout << "Iterating over 1000000 entities, three components, runtime view" << std::endl;
  436. for(std::uint64_t i = 0; i < 1000000L; i++) {
  437. const auto entity = registry.create();
  438. registry.assign<position>(entity);
  439. registry.assign<velocity>(entity);
  440. registry.assign<comp<0>>(entity);
  441. }
  442. auto test = [&registry](auto func) {
  443. using component_type = typename entt::registry::component_type;
  444. component_type types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
  445. timer timer;
  446. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  447. timer.elapsed();
  448. };
  449. test([](auto) {});
  450. test([&registry](auto entity) {
  451. registry.get<position>(entity).x = {};
  452. registry.get<velocity>(entity).x = {};
  453. registry.get<comp<0>>(entity).x = {};
  454. });
  455. }
  456. TEST(Benchmark, IterateThreeComponentsRuntime1MHalf) {
  457. entt::registry registry;
  458. std::cout << "Iterating over 1000000 entities, three components, half of the entities have all the components, runtime view" << std::endl;
  459. for(std::uint64_t i = 0; i < 1000000L; i++) {
  460. const auto entity = registry.create();
  461. registry.assign<velocity>(entity);
  462. registry.assign<comp<0>>(entity);
  463. if(i % 2) {
  464. registry.assign<position>(entity);
  465. }
  466. }
  467. auto test = [&registry](auto func) {
  468. using component_type = typename entt::registry::component_type;
  469. component_type types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
  470. timer timer;
  471. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  472. timer.elapsed();
  473. };
  474. test([](auto) {});
  475. test([&registry](auto entity) {
  476. registry.get<position>(entity).x = {};
  477. registry.get<velocity>(entity).x = {};
  478. registry.get<comp<0>>(entity).x = {};
  479. });
  480. }
  481. TEST(Benchmark, IterateThreeComponentsRuntime1MOne) {
  482. entt::registry registry;
  483. std::cout << "Iterating over 1000000 entities, three components, only one entity has all the components, runtime view" << std::endl;
  484. for(std::uint64_t i = 0; i < 1000000L; i++) {
  485. const auto entity = registry.create();
  486. registry.assign<velocity>(entity);
  487. registry.assign<comp<0>>(entity);
  488. if(i == 5000000L) {
  489. registry.assign<position>(entity);
  490. }
  491. }
  492. auto test = [&registry](auto func) {
  493. using component_type = typename entt::registry::component_type;
  494. component_type types[] = { registry.type<position>(), registry.type<velocity>(), registry.type<comp<0>>() };
  495. timer timer;
  496. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  497. timer.elapsed();
  498. };
  499. test([](auto) {});
  500. test([&registry](auto entity) {
  501. registry.get<position>(entity).x = {};
  502. registry.get<velocity>(entity).x = {};
  503. registry.get<comp<0>>(entity).x = {};
  504. });
  505. }
  506. TEST(Benchmark, IterateFiveComponents1M) {
  507. entt::registry registry;
  508. std::cout << "Iterating over 1000000 entities, five components" << std::endl;
  509. for(std::uint64_t i = 0; i < 1000000L; i++) {
  510. const auto entity = registry.create();
  511. registry.assign<position>(entity);
  512. registry.assign<velocity>(entity);
  513. registry.assign<comp<0>>(entity);
  514. registry.assign<comp<1>>(entity);
  515. registry.assign<comp<2>>(entity);
  516. }
  517. auto test = [&registry](auto func) {
  518. timer timer;
  519. registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  520. timer.elapsed();
  521. };
  522. test([](const auto &...) {});
  523. test([](auto &... comp) {
  524. ((comp.x = {}), ...);
  525. });
  526. }
  527. TEST(Benchmark, IterateFiveComponents1MHalf) {
  528. entt::registry registry;
  529. std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components" << std::endl;
  530. for(std::uint64_t i = 0; i < 1000000L; i++) {
  531. const auto entity = registry.create();
  532. registry.assign<velocity>(entity);
  533. registry.assign<comp<0>>(entity);
  534. registry.assign<comp<1>>(entity);
  535. registry.assign<comp<2>>(entity);
  536. if(i % 2) {
  537. registry.assign<position>(entity);
  538. }
  539. }
  540. auto test = [&registry](auto func) {
  541. timer timer;
  542. registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  543. timer.elapsed();
  544. };
  545. test([](const auto &...) {});
  546. test([](auto &... comp) {
  547. ((comp.x = {}), ...);
  548. });
  549. }
  550. TEST(Benchmark, IterateFiveComponents1MOne) {
  551. entt::registry registry;
  552. std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components" << std::endl;
  553. for(std::uint64_t i = 0; i < 1000000L; i++) {
  554. const auto entity = registry.create();
  555. registry.assign<velocity>(entity);
  556. registry.assign<comp<0>>(entity);
  557. registry.assign<comp<1>>(entity);
  558. registry.assign<comp<2>>(entity);
  559. if(i == 5000000L) {
  560. registry.assign<position>(entity);
  561. }
  562. }
  563. auto test = [&registry](auto func) {
  564. timer timer;
  565. registry.view<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  566. timer.elapsed();
  567. };
  568. test([](const auto &...) {});
  569. test([](auto &... comp) {
  570. ((comp.x = {}), ...);
  571. });
  572. }
  573. TEST(Benchmark, IterateFiveComponentsNonOwningGroup1M) {
  574. entt::registry registry;
  575. registry.group<>(entt::get<position, velocity, comp<0>, comp<1>, comp<2>>);
  576. std::cout << "Iterating over 1000000 entities, five components, non owning group" << std::endl;
  577. for(std::uint64_t i = 0; i < 1000000L; i++) {
  578. const auto entity = registry.create();
  579. registry.assign<position>(entity);
  580. registry.assign<velocity>(entity);
  581. registry.assign<comp<0>>(entity);
  582. registry.assign<comp<1>>(entity);
  583. registry.assign<comp<2>>(entity);
  584. }
  585. auto test = [&registry](auto func) {
  586. timer timer;
  587. registry.group<>(entt::get<position, velocity, comp<0>, comp<1>, comp<2>>).each(func);
  588. timer.elapsed();
  589. };
  590. test([](const auto &...) {});
  591. test([](auto &... comp) {
  592. ((comp.x = {}), ...);
  593. });
  594. }
  595. TEST(Benchmark, IterateFiveComponentsFullOwningGroup1M) {
  596. entt::registry registry;
  597. registry.group<position, velocity, comp<0>, comp<1>, comp<2>>();
  598. std::cout << "Iterating over 1000000 entities, five components, full owning group" << std::endl;
  599. for(std::uint64_t i = 0; i < 1000000L; i++) {
  600. const auto entity = registry.create();
  601. registry.assign<position>(entity);
  602. registry.assign<velocity>(entity);
  603. registry.assign<comp<0>>(entity);
  604. registry.assign<comp<1>>(entity);
  605. registry.assign<comp<2>>(entity);
  606. }
  607. auto test = [&registry](auto func) {
  608. timer timer;
  609. registry.group<position, velocity, comp<0>, comp<1>, comp<2>>().each(func);
  610. timer.elapsed();
  611. };
  612. test([](const auto &...) {});
  613. test([](auto &... comp) {
  614. ((comp.x = {}), ...);
  615. });
  616. }
  617. TEST(Benchmark, IterateFiveComponentsPartialFourOfFiveOwningGroup1M) {
  618. entt::registry registry;
  619. registry.group<position, velocity, comp<0>, comp<1>>(entt::get<comp<2>>);
  620. std::cout << "Iterating over 1000000 entities, five components, partial (4 of 5) owning group" << std::endl;
  621. for(std::uint64_t i = 0; i < 1000000L; i++) {
  622. const auto entity = registry.create();
  623. registry.assign<position>(entity);
  624. registry.assign<velocity>(entity);
  625. registry.assign<comp<0>>(entity);
  626. registry.assign<comp<1>>(entity);
  627. registry.assign<comp<2>>(entity);
  628. }
  629. auto test = [&registry](auto func) {
  630. timer timer;
  631. registry.group<position, velocity, comp<0>, comp<1>>(entt::get<comp<2>>).each(func);
  632. timer.elapsed();
  633. };
  634. test([](const auto &...) {});
  635. test([](auto &... comp) {
  636. ((comp.x = {}), ...);
  637. });
  638. }
  639. TEST(Benchmark, IterateFiveComponentsPartialThreeOfFiveOwningGroup1M) {
  640. entt::registry registry;
  641. registry.group<position, velocity, comp<0>>(entt::get<comp<1>, comp<2>>);
  642. std::cout << "Iterating over 1000000 entities, five components, partial (3 of 5) owning group" << std::endl;
  643. for(std::uint64_t i = 0; i < 1000000L; i++) {
  644. const auto entity = registry.create();
  645. registry.assign<position>(entity);
  646. registry.assign<velocity>(entity);
  647. registry.assign<comp<0>>(entity);
  648. registry.assign<comp<1>>(entity);
  649. registry.assign<comp<2>>(entity);
  650. }
  651. auto test = [&registry](auto func) {
  652. timer timer;
  653. registry.group<position, velocity, comp<0>>(entt::get<comp<1>, comp<2>>).each(func);
  654. timer.elapsed();
  655. };
  656. test([](const auto &...) {});
  657. test([](auto &... comp) {
  658. ((comp.x = {}), ...);
  659. });
  660. }
  661. TEST(Benchmark, IterateFiveComponentsRuntime1M) {
  662. entt::registry registry;
  663. std::cout << "Iterating over 1000000 entities, five components, runtime view" << std::endl;
  664. for(std::uint64_t i = 0; i < 1000000L; i++) {
  665. const auto entity = registry.create();
  666. registry.assign<position>(entity);
  667. registry.assign<velocity>(entity);
  668. registry.assign<comp<0>>(entity);
  669. registry.assign<comp<1>>(entity);
  670. registry.assign<comp<2>>(entity);
  671. }
  672. auto test = [&registry](auto func) {
  673. using component_type = typename entt::registry::component_type;
  674. component_type types[] = {
  675. registry.type<position>(),
  676. registry.type<velocity>(),
  677. registry.type<comp<0>>(),
  678. registry.type<comp<1>>(),
  679. registry.type<comp<2>>()
  680. };
  681. timer timer;
  682. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  683. timer.elapsed();
  684. };
  685. test([](auto) {});
  686. test([&registry](auto entity) {
  687. registry.get<position>(entity).x = {};
  688. registry.get<velocity>(entity).x = {};
  689. registry.get<comp<0>>(entity).x = {};
  690. registry.get<comp<1>>(entity).x = {};
  691. registry.get<comp<2>>(entity).x = {};
  692. });
  693. }
  694. TEST(Benchmark, IterateFiveComponentsRuntime1MHalf) {
  695. entt::registry registry;
  696. std::cout << "Iterating over 1000000 entities, five components, half of the entities have all the components, runtime view" << std::endl;
  697. for(std::uint64_t i = 0; i < 1000000L; i++) {
  698. const auto entity = registry.create();
  699. registry.assign<velocity>(entity);
  700. registry.assign<comp<0>>(entity);
  701. registry.assign<comp<1>>(entity);
  702. registry.assign<comp<2>>(entity);
  703. if(i % 2) {
  704. registry.assign<position>(entity);
  705. }
  706. }
  707. auto test = [&registry](auto func) {
  708. using component_type = typename entt::registry::component_type;
  709. component_type types[] = {
  710. registry.type<position>(),
  711. registry.type<velocity>(),
  712. registry.type<comp<0>>(),
  713. registry.type<comp<1>>(),
  714. registry.type<comp<2>>()
  715. };
  716. timer timer;
  717. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  718. timer.elapsed();
  719. };
  720. test([](auto) {});
  721. test([&registry](auto entity) {
  722. registry.get<position>(entity).x = {};
  723. registry.get<velocity>(entity).x = {};
  724. registry.get<comp<0>>(entity).x = {};
  725. registry.get<comp<1>>(entity).x = {};
  726. registry.get<comp<2>>(entity).x = {};
  727. });
  728. }
  729. TEST(Benchmark, IterateFiveComponentsRuntime1MOne) {
  730. entt::registry registry;
  731. std::cout << "Iterating over 1000000 entities, five components, only one entity has all the components, runtime view" << std::endl;
  732. for(std::uint64_t i = 0; i < 1000000L; i++) {
  733. const auto entity = registry.create();
  734. registry.assign<velocity>(entity);
  735. registry.assign<comp<0>>(entity);
  736. registry.assign<comp<1>>(entity);
  737. registry.assign<comp<2>>(entity);
  738. if(i == 5000000L) {
  739. registry.assign<position>(entity);
  740. }
  741. }
  742. auto test = [&registry](auto func) {
  743. using component_type = typename entt::registry::component_type;
  744. component_type types[] = {
  745. registry.type<position>(),
  746. registry.type<velocity>(),
  747. registry.type<comp<0>>(),
  748. registry.type<comp<1>>(),
  749. registry.type<comp<2>>()
  750. };
  751. timer timer;
  752. registry.runtime_view(std::begin(types), std::end(types)).each(func);
  753. timer.elapsed();
  754. };
  755. test([](auto) {});
  756. test([&registry](auto entity) {
  757. registry.get<position>(entity).x = {};
  758. registry.get<velocity>(entity).x = {};
  759. registry.get<comp<0>>(entity).x = {};
  760. registry.get<comp<1>>(entity).x = {};
  761. registry.get<comp<2>>(entity).x = {};
  762. });
  763. }
  764. TEST(Benchmark, IteratePathological) {
  765. entt::registry registry;
  766. std::cout << "Pathological case" << std::endl;
  767. for(std::uint64_t i = 0; i < 500000L; i++) {
  768. const auto entity = registry.create();
  769. registry.assign<position>(entity);
  770. registry.assign<velocity>(entity);
  771. registry.assign<comp<0>>(entity);
  772. }
  773. for(auto i = 0; i < 10; ++i) {
  774. registry.each([i = 0, &registry](const auto entity) mutable {
  775. if(i % 7) { registry.remove<position>(entity); }
  776. if(i % 11) { registry.remove<velocity>(entity); }
  777. if(i % 13) { registry.remove<comp<0>>(entity); }
  778. if(i % 17) { registry.destroy(entity); }
  779. });
  780. for(std::uint64_t j = 0; j < 50000L; j++) {
  781. const auto entity = registry.create();
  782. registry.assign<position>(entity);
  783. registry.assign<velocity>(entity);
  784. registry.assign<comp<0>>(entity);
  785. }
  786. }
  787. auto test = [&registry](auto func) {
  788. timer timer;
  789. registry.view<position, velocity, comp<0>>().each(func);
  790. timer.elapsed();
  791. };
  792. test([](const auto &...) {});
  793. test([](auto &... comp) {
  794. ((comp.x = {}), ...);
  795. });
  796. }
  797. TEST(Benchmark, IteratePathologicalNonOwningGroup) {
  798. entt::registry registry;
  799. registry.group<>(entt::get<position, velocity, comp<0>>);
  800. std::cout << "Pathological case" << std::endl;
  801. for(std::uint64_t i = 0; i < 500000L; i++) {
  802. const auto entity = registry.create();
  803. registry.assign<position>(entity);
  804. registry.assign<velocity>(entity);
  805. registry.assign<comp<0>>(entity);
  806. }
  807. for(auto i = 0; i < 10; ++i) {
  808. registry.each([i = 0, &registry](const auto entity) mutable {
  809. if(i % 7) { registry.remove<position>(entity); }
  810. if(i % 11) { registry.remove<velocity>(entity); }
  811. if(i % 13) { registry.remove<comp<0>>(entity); }
  812. if(i % 17) { registry.destroy(entity); }
  813. });
  814. for(std::uint64_t j = 0; j < 50000L; j++) {
  815. const auto entity = registry.create();
  816. registry.assign<position>(entity);
  817. registry.assign<velocity>(entity);
  818. registry.assign<comp<0>>(entity);
  819. }
  820. }
  821. auto test = [&registry](auto func) {
  822. timer timer;
  823. registry.group<>(entt::get<position, velocity, comp<0>>).each(func);
  824. timer.elapsed();
  825. };
  826. test([](const auto &...) {});
  827. test([](auto &... comp) {
  828. ((comp.x = {}), ...);
  829. });
  830. }
  831. TEST(Benchmark, IteratePathologicalFullOwningGroup) {
  832. entt::registry registry;
  833. registry.group<position, velocity, comp<0>>();
  834. std::cout << "Pathological case" << std::endl;
  835. for(std::uint64_t i = 0; i < 500000L; i++) {
  836. const auto entity = registry.create();
  837. registry.assign<position>(entity);
  838. registry.assign<velocity>(entity);
  839. registry.assign<comp<0>>(entity);
  840. }
  841. for(auto i = 0; i < 10; ++i) {
  842. registry.each([i = 0, &registry](const auto entity) mutable {
  843. if(i % 7) { registry.remove<position>(entity); }
  844. if(i % 11) { registry.remove<velocity>(entity); }
  845. if(i % 13) { registry.remove<comp<0>>(entity); }
  846. if(i % 17) { registry.destroy(entity); }
  847. });
  848. for(std::uint64_t j = 0; j < 50000L; j++) {
  849. const auto entity = registry.create();
  850. registry.assign<position>(entity);
  851. registry.assign<velocity>(entity);
  852. registry.assign<comp<0>>(entity);
  853. }
  854. }
  855. auto test = [&registry](auto func) {
  856. timer timer;
  857. registry.group<position, velocity, comp<0>>().each(func);
  858. timer.elapsed();
  859. };
  860. test([](const auto &...) {});
  861. test([](auto &... comp) {
  862. ((comp.x = {}), ...);
  863. });
  864. }
  865. TEST(Benchmark, IteratePathologicalPartialOwningGroup) {
  866. entt::registry registry;
  867. registry.group<position, velocity>(entt::get<comp<0>>);
  868. std::cout << "Pathological case" << std::endl;
  869. for(std::uint64_t i = 0; i < 500000L; i++) {
  870. const auto entity = registry.create();
  871. registry.assign<position>(entity);
  872. registry.assign<velocity>(entity);
  873. registry.assign<comp<0>>(entity);
  874. }
  875. for(auto i = 0; i < 10; ++i) {
  876. registry.each([i = 0, &registry](const auto entity) mutable {
  877. if(i % 7) { registry.remove<position>(entity); }
  878. if(i % 11) { registry.remove<velocity>(entity); }
  879. if(i % 13) { registry.remove<comp<0>>(entity); }
  880. if(i % 17) { registry.destroy(entity); }
  881. });
  882. for(std::uint64_t j = 0; j < 50000L; j++) {
  883. const auto entity = registry.create();
  884. registry.assign<position>(entity);
  885. registry.assign<velocity>(entity);
  886. registry.assign<comp<0>>(entity);
  887. }
  888. }
  889. auto test = [&registry](auto func) {
  890. timer timer;
  891. registry.group<position, velocity>(entt::get<comp<0>>).each(func);
  892. timer.elapsed();
  893. };
  894. test([](const auto &...) {});
  895. test([](auto &... comp) {
  896. ((comp.x = {}), ...);
  897. });
  898. }
  899. TEST(Benchmark, SortSingle) {
  900. entt::registry registry;
  901. std::cout << "Sort 150000 entities, one component" << std::endl;
  902. for(std::uint64_t i = 0; i < 150000L; i++) {
  903. const auto entity = registry.create();
  904. registry.assign<position>(entity, i, i);
  905. }
  906. timer timer;
  907. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  908. return lhs.x < rhs.x && lhs.y < rhs.y;
  909. });
  910. timer.elapsed();
  911. }
  912. TEST(Benchmark, SortMulti) {
  913. entt::registry registry;
  914. std::cout << "Sort 150000 entities, two components" << std::endl;
  915. for(std::uint64_t i = 0; i < 150000L; i++) {
  916. const auto entity = registry.create();
  917. registry.assign<position>(entity, i, i);
  918. registry.assign<velocity>(entity, i, i);
  919. }
  920. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  921. return lhs.x < rhs.x && lhs.y < rhs.y;
  922. });
  923. timer timer;
  924. registry.sort<velocity, position>();
  925. timer.elapsed();
  926. }
  927. TEST(Benchmark, AlmostSortedStdSort) {
  928. entt::registry registry;
  929. entt::entity entities[3];
  930. std::cout << "Sort 150000 entities, almost sorted, std::sort" << std::endl;
  931. for(std::uint64_t i = 0; i < 150000L; i++) {
  932. const auto entity = registry.create();
  933. registry.assign<position>(entity, i, i);
  934. if(!(i % 50000)) {
  935. entities[i / 50000] = entity;
  936. }
  937. }
  938. for(std::uint64_t i = 0; i < 3; ++i) {
  939. registry.destroy(entities[i]);
  940. const auto entity = registry.create();
  941. registry.assign<position>(entity, 50000 * i, 50000 * i);
  942. }
  943. timer timer;
  944. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  945. return lhs.x > rhs.x && lhs.y > rhs.y;
  946. });
  947. timer.elapsed();
  948. }
  949. TEST(Benchmark, AlmostSortedInsertionSort) {
  950. entt::registry registry;
  951. entt::entity entities[3];
  952. std::cout << "Sort 150000 entities, almost sorted, insertion sort" << std::endl;
  953. for(std::uint64_t i = 0; i < 150000L; i++) {
  954. const auto entity = registry.create();
  955. registry.assign<position>(entity, i, i);
  956. if(!(i % 50000)) {
  957. entities[i / 50000] = entity;
  958. }
  959. }
  960. for(std::uint64_t i = 0; i < 3; ++i) {
  961. registry.destroy(entities[i]);
  962. const auto entity = registry.create();
  963. registry.assign<position>(entity, 50000 * i, 50000 * i);
  964. }
  965. timer timer;
  966. registry.sort<position>([](const auto &lhs, const auto &rhs) {
  967. return lhs.x > rhs.x && lhs.y > rhs.y;
  968. }, entt::insertion_sort{});
  969. timer.elapsed();
  970. }