1 module tests.tests;
2 /*
3 import std.experimental.allocator;
4 import std.experimental.allocator.mallocator;*/
5 
6 import bubel.ecs.entity;
7 import bubel.ecs.events;
8 import bubel.ecs.manager;
9 import bubel.ecs.system;
10 import bubel.ecs.attributes;
11 import bubel.ecs.core;
12 
13 version (WebAssembly)
14 {
15 	extern (C) int printf(scope const char* format, ...) @nogc nothrow @system;
16 
17 	alias int time_t;
18 	alias int clockid_t;
19 	enum CLOCK_REALTIME = 0;
20 
21 	struct timespec
22 	{
23 		time_t tv_sec;
24 		int tv_nsec;
25 	}
26 
27 	extern (C) int clock_gettime(clockid_t, timespec*) @nogc nothrow @system;
28 
29 	struct Time
30 	{
31 
32 		static long getUSecTime()
33 		{
34 			time_t time;
35 			timespec spec;
36 
37 			clock_gettime(CLOCK_REALTIME, &spec);
38 
39 			//time = spec.tv_sec;
40 			return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000; //time / 1000_000;
41 		}
42 	}
43 
44 	extern (C) void _start()
45 	{
46 	}
47 }
48 else version (Windows)
49 {
50 	import core.stdc.stdio : printf;
51 	import core.sys.windows.windows;
52 
53 	struct Time
54 	{
55 		static long getUSecTime()
56 		{
57 			LARGE_INTEGER time, freq;
58 			QueryPerformanceFrequency(&freq);
59 			QueryPerformanceCounter(&time);
60 			return time.QuadPart / (freq.QuadPart / 1000_000);
61 		}
62 	}
63 }
64 else version (Posix)
65 {
66 	import core.stdc.stdio : printf;
67 	import core.sys.posix.time;
68 
69 	struct Time
70 	{
71 		static long getUSecTime()
72 		{
73 			time_t time;
74 			timespec spec;
75 
76 			clock_gettime(CLOCK_REALTIME, &spec);
77 
78 			//time = spec.tv_sec;
79 			return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000; //time / 1000_000;
80 		}
81 	}
82 }
83 
84 struct TestEvent
85 {
86 	mixin ECS.Event; //__gshared ushort event_id;
87 	int a;
88 }
89 
90 struct TestEvent2
91 {
92 	mixin ECS.Event; //__gshared ushort event_id;
93 	float a;
94 }
95 
96 static struct CPosition
97 {
98 	mixin ECS.Component;
99 	float x;
100 	float y;
101 }
102 
103 static struct TestComp
104 {
105 	mixin ECS.Component; //__gshared becsID!ushort;
106 	int a = 1;
107 	ulong b = 2;
108 
109 	static void serializeComponent(SerializeVector output)
110 	{
111 
112 	}
113 
114 	static void deserializeComponent(ubyte[] data)
115 	{
116 
117 	}
118 }
119 
120 static struct TestComp2
121 {
122 	mixin ECS.Component; //__gshared becsID!ushort;
123 	int b = 3;
124 	int a = 4;
125 
126 	static void serializeComponent(ref TestComp comp, SerializeVector output)
127 	{
128 
129 	}
130 
131 	static void deserializeComponent(ref TestComp comp, ubyte[] data)
132 	{
133 
134 	}
135 }
136 
137 static struct TestComp3
138 {
139 	mixin ECS.Component; //__gshared becsID!ushort;
140 	uint gg = 5; //good game
141 	uint bg = 6; //bad game
142 
143 	void serializeComponent(SerializeVector output)
144 	{
145 
146 	}
147 
148 	void deserializeComponent(ubyte[] data)
149 	{
150 
151 	}
152 }
153 
154 static struct TestComp4
155 {
156 	mixin ECS.Component; //__gshared becsID!ushort;
157 	uint gg = 7; //good game
158 	uint bg = 8; //bad game
159 	ulong a = 9;
160 	ulong b = 10;
161 	ulong c = 11;
162 	ulong g = 12;
163 
164 	static void serializeComponent(ref TestComp comp, SerializeVector output)
165 	{
166 
167 	}
168 
169 	static void deserializeComponent(ref TestComp comp, ubyte[] data)
170 	{
171 
172 	}
173 }
174 
175 static struct TestComp5
176 {
177 	mixin ECS.Component; //__gshared becsID!ushort;
178 	uint gg = 7; //good game
179 	uint bg = 8; //bad game
180 	ulong a = 9;
181 	ulong b = 10;
182 	ulong c = 11;
183 	ulong g = 12;
184 
185 	static void serializeComponent(ref TestComp comp, SerializeVector output)
186 	{
187 
188 	}
189 
190 	static void deserializeComponent(ref TestComp comp, ubyte[] data)
191 	{
192 
193 	}
194 }
195 
196 struct EverySystem
197 {
198 	mixin ECS.System;
199 
200 	struct EntitiesData
201 	{
202 		uint length;
203 		Entity[] entity;
204 		CPosition[] pos;
205 	}
206 
207 	void onUpdate(EntitiesData data)
208 	{
209 		foreach(i;0..data.length)
210 		{
211 			data.pos[i].x++;
212 			data.pos[i].y++;
213 		}
214 	}
215 
216 	void iterate(EntitiesData data)
217 	{
218 		foreach(i;0..data.length)
219 		{
220 			data.pos[i].x++;
221 			data.pos[i].y++;
222 		}
223 	}
224 
225 	void free(EntitiesData data)
226 	{
227 		foreach(i;0..data.length)
228 		{
229 			gEntityManager.removeEntity(data.entity[i].id);
230 		}
231 	}
232 
233 	void addOne(EntitiesData data)
234 	{
235 		foreach(i;0..data.length)
236 		{
237 			gEntityManager.addComponents(data.entity[i].id, TestComp2());
238 		}
239 	}
240 }
241 
242 struct ChangeTestSystem
243 {
244 	mixin ECS.System!16; //__gshared ushort system_id;
245 
246 	void onCreate()
247 	{
248 		//writeln("On Change Test System create.");
249 		printf("On Change Test System create.\n");
250 	}
251 
252 	void onCreate(int i)
253 	{
254 		//writeln("On Change Test System create.");
255 		printf("On Change Test System create.\n");
256 	}
257 
258 	void onDestroy()
259 	{
260 		//writeln("On Change Test System destroy.");
261 		printf("On Change Test System destroy.\n");
262 	}
263 
264 	void onAddEntity(EntitiesData data)
265 	{
266 		//printf("Entity added! ID: ");
267 		foreach (i; 0 .. data.length)
268 			printf("Entity added! ID: %u\n", cast(uint) data.entites[i].id.id);
269 		////writeln("Entity added! ID: ", data.entites[i].id);
270 	}
271 
272 	void onRemoveEntity(EntitiesData data)
273 	{
274 		////writeln("Entity removed! ID: ", data.entites[0].id);
275 		printf("Entity removed! ID: %u\n", cast(uint) data.entites[0].id.id);
276 	}
277 
278 	void onChangeEntity(EntitiesData data)
279 	{
280 		////writeln("Entity changed! ID: ", data.entites[0].id);
281 		printf("Entity changed! ID: %u\n", cast(uint) data.entites[0].id.id);
282 	}
283 
284 	bool onBegin()
285 	{
286 		////writeln("On Test System begin.");
287 		return true;
288 	}
289 
290 	void onEnd()
291 	{
292 		////writeln("On Test System end.");
293 	}
294 
295 	void initialize(ref Entity entity, ref TestComp comp)
296 	{
297 
298 	}
299 
300 	static struct EntitiesData
301 	{
302 		size_t length;
303 		const(Entity)[] entites;
304 		TestComp4[] test4;
305 		@optional TestComp5[] test5;
306 	}
307 
308 	void onUpdate(EntitiesData data)
309 	{
310 		foreach (i; 0 .. data.length)
311 		{
312 
313 		}
314 	}
315 }
316 
317 struct TestSystem
318 {
319 	mixin ECS.System!16; //__gshared ushort system_id;
320 
321 	void onCreate()
322 	{
323 		//writeln("On Test System create.");
324 		printf("On Change Test System create.\n");
325 	}
326 
327 	void onDestroy()
328 	{
329 		//writeln("On Test System destroy.");
330 		printf("On Change Test System destroy.\n");
331 	}
332 
333 	void onAddEntity(EntitiesData data)
334 	{
335 		//foreach(i;0..data.length)
336 		////writeln("Entity added ID: ",data.entites[i].id.id);
337 	}
338 	/*
339 	void onRemoveEntity(EntitiesData data)
340 	{
341 		////writeln("Entity destroyed ID: ",data.entites[0].id);
342 	}*/
343 
344 	bool onBegin()
345 	{
346 		////writeln("On Test System begin.");
347 		return true;
348 	}
349 
350 	void onEnd()
351 	{
352 		////writeln("On Test System end.");
353 	}
354 
355 	void initialize(ref Entity entity, ref TestComp comp)
356 	{
357 
358 	}
359 
360 	static struct EntitiesData
361 	{
362 		size_t length;
363 		const(Entity)[] entites;
364 		TestComp[] test;
365 		TestComp2[] test2;
366 		@readonly @optional const(TestComp3)[] test3;
367 		//@excluded TestComp4[] test4;
368 	}
369 
370 	void onUpdate(ref Entity entity, ref TestComp test, ref TestComp2 test2) //, TestComp3* test3) //ref TestComp comp)
371 	{
372 		//assert(cast(size_t)&test % TestComp.alignof == 0);
373 		//assert(cast(size_t)&test2 % TestComp2.alignof == 0);
374 
375 		test.a += 1000;
376 		test.b += 2000;
377 		test2.b += 2;
378 		test2.a = 8;
379 	}
380 
381 	void onUpdate(EntitiesData data)
382 	{
383 		foreach (i; 0 .. data.length)
384 		{
385 			data.test[i].a += 1000;
386 			data.test[i].b += 2000;
387 			data.test2[i].b += 2;
388 			data.test2[i].a = 8;
389 		}
390 	}
391 
392 	void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
393 	{
394 
395 	}
396 }
397 
398 struct TestSystemWithHighPriority
399 {
400 	mixin ECS.System!16; //__gshared ushort system_id;
401 
402 	static struct EntitiesData
403 	{
404 		TestComp[] test;
405 	}
406 
407 	void initialize(ref Entity entity, ref TestComp comp)
408 	{
409 		int o = 1;
410 	}
411 
412 	void onUpdate(EntitiesData data)
413 	{
414 
415 	}
416 }
417 
418 struct Sys1
419 {
420 	mixin ECS.System;
421 
422 	struct EntitiesData
423 	{
424 		TestComp[] comp;
425 	}
426 
427 	void onAddEntity(EntitiesData data)
428 	{
429 
430 	}
431 }
432 
433 struct Sys2
434 {
435 	mixin ECS.System;
436 
437 	struct EntitiesData
438 	{
439 		TestComp[] comp;
440 	}
441 
442 	void onAddEntity(EntitiesData data)
443 	{
444 
445 	}
446 }
447 
448 struct Sys3
449 {
450 	mixin ECS.System;
451 
452 	struct EntitiesData
453 	{
454 		TestComp[] comp;
455 	}
456 
457 	void onAddEntity(EntitiesData data)
458 	{
459 
460 	}
461 
462 	void onUpdate(EntitiesData data)
463 	{
464 
465 	}
466 }
467 
468 struct EmptyEventSystem
469 {
470 	mixin ECS.System;
471 
472 	bool handled = false;
473 
474 	struct EntitiesData
475 	{
476 		uint thread_id;
477 	}
478 
479 	void handleEvent(Entity* entity, TestEvent event)
480 	{
481 		if (!handled)
482 		{
483 			printf("EmptyEventSystem.handleEvent() called!\n");
484 			handled = true;
485 		}
486 		assert(0, "this shouldn't be called!");
487 	}
488 }
489 
490 struct EventSystem
491 {
492 	mixin ECS.System;
493 
494 	bool handled = false;
495 
496 	struct EntitiesData
497 	{
498 		uint thread_id;
499 		TestComp[] comp;
500 	}
501 
502 	void handleEvent(Entity* entity, TestEvent event)
503 	{
504 		if (!handled)
505 		{
506 			printf("EventSystem.handleEvent() called!\n");
507 			handled = true;
508 		}
509 	}
510 
511 	/*void onUpdate(EntitiesData)
512 	{
513 
514 	}*/
515 }
516 
517 struct EmptySystem
518 {
519 	mixin ECS.System;
520 
521 	struct EntitiesData
522 	{
523 		uint thread_id;
524 	}
525 
526 	void onUpdate(EntitiesData data)
527 	{
528 		printf("EmptySystem.onUpdate() - this should be called once per update\n");
529 	}
530 }
531 
532 import std.meta;
533 
534 struct TestSystem2
535 {
536 	mixin ECS.System!16; //__gshared ushort system_id;
537 
538 	/*enum ExcludedComponents
539 	{
540 		TestComp,
541 		TestComp4
542 	}*/
543 
544 	//alias ExcludedComponents = AliasSeq!("TestComp", "TestComp4");
545 	/*
546 	string ExcludedComponents2;*/
547 
548 	static struct EntitiesData
549 	{
550 		short length;
551 		const(Entity)[] entity;
552 		TestComp3[] test;
553 		//@excluded TestComp[] testt;
554 	}
555 
556 	static struct EventInput
557 	{
558 		Entity* entity;
559 		TestComp3* test;
560 		//TestComp* tt;
561 	}
562 
563 	void handleEvent(Entity* entity, TestEvent event)
564 	{
565 		TestComp3* test = entity.getComponent!TestComp3;
566 		test.bg = event.a;
567 		TestEvent2 event2;
568 		event2.a = event.a + 8;
569 		gEntityManager.sendEvent(entity.id, event2);
570 	}
571 
572 	void handleEvent(Entity* entity, TestEvent2 event)
573 	{
574 		TestComp3* test = entity.getComponent!TestComp3;
575 		test.gg = cast(uint) event.a;
576 	}
577 
578 	void onEnable()
579 	{
580 
581 		//writeln("TestSystem2 enabled");
582 		printf("TestSystem2 enabled\n");
583 	}
584 
585 	void onDisable()
586 	{
587 
588 		//writeln("TestSystem2 disabled");
589 		printf("TestSystem2 disabled\n");
590 	}
591 
592 	void initialize(ref Entity entity, ref TestComp comp)
593 	{
594 
595 	}
596 
597 	void onUpdate(EntitiesData data)
598 	{
599 		foreach (i; 0 .. data.test.length)
600 		{
601 			data.test[i].gg += 14;
602 			TestEvent event;
603 			event.a = data.test[i].gg + 4;
604 			gEntityManager.sendEvent(data.entity[i].id, event); //*/
605 			/*TestEvent2 event2;
606 			event2.a = data.test[i].gg + 8;
607 			gEntityManager.sendEvent(data.entity[i].id, event2);//*/
608 			//gEntityManager.sendEvent!(TestEvent)(data.entity[i].id, event);
609 			//gEntityManager.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
610 		}
611 	}
612 
613 	void lateUpdate(ref EntitiesData data)
614 	{
615 		foreach (i; 0 .. data.test.length)
616 		{
617 			data.test[i].gg -= 1;
618 			//gEntityManager.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
619 		}
620 	}
621 
622 }
623 
624 struct ExternalUpdateCallTest
625 {
626 	int print_count = 3;
627 
628 	void update(TestSystem2.EntitiesData data)
629 	{
630 		if (print_count > 0)
631 		{
632 			print_count--;
633 			printf("ExternalUpdateCallTest %u %u\n", data.test[0].gg, cast(uint) data.length);
634 		}
635 	}
636 }
637 
638 version (unittest)
639 {
640 	void main()
641 	{
642 
643 	}
644 }
645 else:
646 	extern (C) int main()
647 {
648 
649 	void dispatch(EntityManager.JobGroup jobs) nothrow @nogc
650 	{
651 		foreach (job; jobs.jobs)
652 		{
653 			////writeln(job);
654 			job.execute();
655 		}
656 	}
657 
658 	uint getID() nothrow @nogc
659 	{
660 		return 0;
661 	}
662 
663 	void writeEntityComponents(Entity* entity)
664 	{
665 
666 		printf("EntityID(%u, %u)", cast(uint) entity.id.id, cast(uint) entity.id.counter);
667 		//write(entity.id);
668 		TestComp* test_comp = entity.getComponent!TestComp;
669 		if (test_comp)
670 			printf("TestComp(%u, %u)", cast(uint) test_comp.a, cast(uint) test_comp.b); //write(*test_comp);
671 		TestComp2* test_comp2 = entity.getComponent!TestComp2;
672 		if (test_comp2)
673 			printf("TestComp2(%u, %u)", cast(uint) test_comp2.b, cast(uint) test_comp2.a); //write(*test_comp2);
674 		TestComp3* test_comp3 = entity.getComponent!TestComp3;
675 		if (test_comp3)
676 			printf("TestComp3(%u, %u)", cast(uint) test_comp3.gg, cast(uint) test_comp3.bg); //write(*test_comp3);
677 		TestComp4* test_comp4 = entity.getComponent!TestComp4;
678 		if (test_comp4)
679 			printf("TestComp4(%u, %u, %u, %u, %u, %u)", test_comp4.gg, test_comp4.bg,
680 					cast(uint) test_comp4.a, cast(uint) test_comp4.b,
681 					cast(uint) test_comp4.c, cast(uint) test_comp4.g); //write(*test_comp4);
682 		printf("\n");
683 		//writeln();
684 		////writeln((cast(uint*) pp)[0 .. 14], " ", pp);
685 	}
686 
687 	EntityManager.initialize(1);
688 
689 	//gEntityManager.setJobDispachFunc(&dispatch);
690 	gEntityManager.setMultithreadingCallbacks(&dispatch, &getID);
691 	//assert(gEntityManager !is null);
692 
693 	gEntityManager.beginRegister();
694 	gEntityManager.registerPass("fixed");
695 
696 	//MonoTime time = MonoTime.currTime;
697 	long time = Time.getUSecTime();
698 
699 	gEntityManager.registerComponent!TestComp2;
700 	gEntityManager.registerComponent!TestComp4;
701 	gEntityManager.registerComponent!TestComp;
702 	gEntityManager.registerComponent!TestComp3;
703 	gEntityManager.registerComponent!TestComp5;
704 	gEntityManager.registerComponent!CPosition;
705 
706 	gEntityManager.registerEvent!TestEvent;
707 	gEntityManager.registerEvent!TestEvent2;
708 
709 	/*ulong dur = (MonoTime.currTime - time).total!"usecs";
710 	//writeln("Components register: ", dur, " usecs");
711 
712 	time = MonoTime.currTime;*/
713 
714 	printf("Components register: %f usecs\n", cast(float)(Time.getUSecTime() - time));
715 	time = Time.getUSecTime();
716 
717 	gEntityManager.registerSystem!TestSystemWithHighPriority(100, "fixed");
718 	gEntityManager.registerSystem!TestSystem(0);
719 	gEntityManager.registerSystem!ChangeTestSystem(0);
720 	gEntityManager.registerSystem!Sys1(10);
721 	gEntityManager.registerSystem!Sys2(-100);
722 	gEntityManager.registerSystem!Sys3(-2);
723 	gEntityManager.registerSystem!EmptySystem(2);
724 	gEntityManager.registerSystem!EmptyEventSystem(2);
725 	gEntityManager.registerSystem!EventSystem(2);
726 	gEntityManager.registerSystem!EverySystem(0);
727 	//gEntityManager.registerSystem!TestSystemWithHighPriority(100);
728 	//gEntityManager.registerSystem!TestSystem2(0);
729 	gEntityManager.endRegister();
730 
731 	/*dur = (MonoTime.currTime - time).total!"usecs";
732 	//writeln("Systems register: ", dur, " usecs");
733 
734 	time = MonoTime.currTime;*/
735 	printf("Systems register: %f usecs\n", cast(float)(Time.getUSecTime() - time));
736 	time = Time.getUSecTime();
737 
738 	//ushort[3] ids = [becsID!TestComp2, becsID!TestComp, becsID!TestComp4];
739 	ushort[2] ids = [becsID!TestComp2, becsID!TestComp];
740 	EntityTemplate* tmpl = gEntityManager.allocateTemplate(ids);
741 
742 	//ushort[3] ids2 = [becsID!TestComp3, becsID!TestComp, becsID!TestComp4];
743 	ushort[2] ids2 = [becsID!TestComp3, becsID!TestComp];
744 	EntityTemplate* tmpl2 = gEntityManager.allocateTemplate(ids2);
745 	////writeln(tmpl.info.components[]);
746 	//*cast(EntityID*) tmpl.entity_data.ptr = EntityID(1, 1);
747 
748 	//dur = (MonoTime.currTime - time).total!"usecs";
749 	//writeln("Template allocating: ", dur, " usecs");
750 	printf("Template allocating: %f usecs\n", cast(float)(Time.getUSecTime() - time));
751 
752 
753 	time = Time.getUSecTime();
754 	ushort[1] empty_ids = [becsID!CPosition];
755 	EntityTemplate* tmpl_empty = gEntityManager.allocateTemplate(empty_ids);
756 
757 	gEntityManager.commit();
758 
759 	time = Time.getUSecTime();
760 
761 	foreach(i;0..4_000_000)gEntityManager.addEntity(tmpl_empty);
762 	gEntityManager.commit();
763 	foreach(i;0..4_000_000)gEntityManager.addEntity(tmpl_empty);
764 	gEntityManager.commit();
765 	foreach(i;0..2_000_000)gEntityManager.addEntity(tmpl_empty);
766 	gEntityManager.commit();
767 
768 	printf("Adding 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
769 
770 	gEntityManager.commit();
771 	time = Time.getUSecTime();
772 	gEntityManager.callEntitiesFunction!EverySystem(&gEntityManager.getSystem!EverySystem().iterate);
773 	printf("Iterate 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
774 
775 	gEntityManager.begin();
776 	time = Time.getUSecTime();	
777 	gEntityManager.update();
778 	printf("Iterate 1M entities (update): %f usecs\n", cast(float)(Time.getUSecTime() - time));
779 	gEntityManager.end();
780 
781 	time = Time.getUSecTime();
782 	gEntityManager.callEntitiesFunction!EverySystem(&gEntityManager.getSystem!EverySystem().free);
783 	gEntityManager.commit();
784 	printf("Deleting 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
785 
786 	time = Time.getUSecTime();
787 
788 	foreach(i;0..4_000_000)gEntityManager.addEntity(tmpl_empty);
789 	gEntityManager.commit();
790 	foreach(i;0..4_000_000)gEntityManager.addEntity(tmpl_empty);
791 	gEntityManager.commit();
792 	foreach(i;0..2_000_000)gEntityManager.addEntity(tmpl_empty);
793 	gEntityManager.commit();
794 
795 	printf("Adding 1M entities (prealloc): %f usecs\n", cast(float)(Time.getUSecTime() - time));
796 
797 	gEntityManager.commit();
798 	time = Time.getUSecTime();
799 	gEntityManager.callEntitiesFunction!EverySystem(&gEntityManager.getSystem!EverySystem().addOne);
800 	gEntityManager.commit();
801 	printf("Adding 1M component: %f usecs\n", cast(float)(Time.getUSecTime() - time));
802 
803 	gEntityManager.commit();
804 	gEntityManager.callEntitiesFunction!EverySystem(&gEntityManager.getSystem!EverySystem().free);
805 	gEntityManager.commit();
806 
807 	time = Time.getUSecTime();
808 
809 	EntityID entity;
810 
811 	{
812 		entity = gEntityManager.addEntity(tmpl).id;
813 		writeEntityComponents(gEntityManager.getEntity(entity));
814 		EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(
815 				gEntityManager.getEntity(entity));
816 		EntityManager.EntityInfo* info = block.type_info;
817 		//writeln(info.add_listeners);
818 		//if(info)assert(0);
819 	}
820 
821 	//time = MonoTime.currTime;
822 	time = Time.getUSecTime();
823 
824 	//foreach(i; 0..1_000_000)gEntityManager.addEntity(tmpl);
825 
826 	//foreach(i; 0..1_000_000)gEntityManager.removeEntity(gEntityManager.addEntity(tmpl).id);
827 
828 	import bubel.ecs.std;
829 
830 	EntityID[] idss = Mallocator.makeArray!EntityID(5000); //[5000]
831 	//scope(exit)Mallocator.dispose(idss);
832 
833 	foreach (i; 0 .. 200)
834 	{
835 		gEntityManager.begin();
836 		foreach (j; 0 .. 5_000)
837 			idss[j] = gEntityManager.addEntity(tmpl).id;
838 		foreach (j; 0 .. 5_000)
839 			gEntityManager.removeEntity(idss[j]);
840 		gEntityManager.end();
841 	}
842 	gEntityManager.commit();
843 
844 	//dur = (MonoTime.currTime - time).total!"usecs";
845 	//writeln("Entities adding: ", dur, " usecs");
846 	printf("Entities adding: %f usecs\n", cast(float)(Time.getUSecTime() - time));
847 	time = Time.getUSecTime();
848 
849 	uint blocks = 0;
850 	foreach (info; &gEntityManager.entities_infos.byValue)
851 	{
852 		EntityManager.EntitiesBlock* block = info.first_block;
853 		while (block !is null)
854 		{
855 			block = block.next_block;
856 			blocks++;
857 		}
858 	}
859 	//writeln("Entities blocks: ", blocks);
860 	printf("Entities blocks: %u\n", blocks);
861 
862 	//foreach(j; 0..1_000)gEntityManager.addEntity(tmpl);
863 
864 	gEntityManager.beginRegister();
865 	gEntityManager.registerSystem!TestSystem2(0);
866 	gEntityManager.endRegister();
867 
868 	//gEntityManager.generateDependencies();
869 
870 	//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
871 	//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+48)) == EntityID(1,1));
872 
873 	EntityID entity2;
874 
875 	//time = MonoTime.currTime;
876 	time = Time.getUSecTime();
877 
878 	EntityID[] entities = Mallocator.makeArray!EntityID(1_000_000);
879 	foreach (i; 0 .. 500_000)
880 	{
881 		entity2 = gEntityManager.addEntity(tmpl).id;
882 		entities[i * 2] = entity2;
883 		entities[i * 2 + 1] = gEntityManager.addEntity(tmpl2).id;
884 	}
885 
886 	gEntityManager.commit();
887 	//dur = (MonoTime.currTime - time).total!"usecs";
888 	//writeln("Entities adding2: ", dur, " usecs");
889 
890 	//time = MonoTime.currTime;
891 	printf("Entities adding2: %f usecs\n", cast(float)(Time.getUSecTime() - time));
892 	time = Time.getUSecTime();
893 
894 	foreach (i; 0 .. 1_000_000)
895 	{
896 		gEntityManager.addComponents(entities[i], TestComp5());
897 		if ((i & 0x00FFFF) == 0)
898 			gEntityManager.commit();
899 	}
900 
901 	gEntityManager.commit();
902 	//dur = (MonoTime.currTime - time).total!"usecs";
903 	//writeln("Components adding: ", dur, " usecs");
904 
905 	//time = MonoTime.currTime;
906 	printf("Components adding: %f usecs\n", cast(float)(Time.getUSecTime() - time));
907 	time = Time.getUSecTime();
908 
909 	foreach (i; 0 .. 1_000_000)
910 	{
911 		gEntityManager.removeComponents!TestComp5(entities[i]);
912 		//if((i & 0x00FFFF) == 0)gEntityManager.commit();
913 	}
914 
915 	gEntityManager.commit();
916 	//dur = (MonoTime.currTime - time).total!"usecs";
917 	//writeln("Components removing: ", dur, " usecs");
918 	printf("Components removing: %f usecs\n", cast(float)(Time.getUSecTime() - time));
919 	time = Time.getUSecTime();
920 
921 	Mallocator.dispose(entities);
922 
923 	//time = MonoTime.currTime;
924 	time = Time.getUSecTime();
925 
926 	gEntityManager.begin();
927 	//gEntityManager.updateMT();
928 	gEntityManager.update();
929 	gEntityManager.end();
930 
931 	//dur = (MonoTime.currTime - time).total!"usecs";
932 	//writeln("Update: ", dur, " usecs");
933 	printf("Update: %f usecs\n", cast(float)(Time.getUSecTime() - time));
934 
935 	writeEntityComponents(gEntityManager.getEntity(entity2));
936 
937 	//time = MonoTime.currTime;
938 	time = Time.getUSecTime();
939 
940 	gEntityManager.begin();
941 	gEntityManager.updateMT();
942 	//gEntityManager.update();
943 	gEntityManager.end();
944 
945 	//dur = (MonoTime.currTime - time).total!"usecs";
946 	//writeln("Update: ", dur, " usecs");
947 	printf("Update: %f usecs\n", cast(float)(Time.getUSecTime() - time));
948 
949 	writeEntityComponents(gEntityManager.getEntity(entity2));
950 
951 	//time = MonoTime.currTime;
952 	time = Time.getUSecTime();
953 
954 	gEntityManager.begin();
955 	gEntityManager.updateMT();
956 	//gEntityManager.update();
957 	gEntityManager.end();
958 
959 	//dur = (MonoTime.currTime - time).total!"usecs";
960 	//writeln("Update: ", dur, " usecs");
961 	printf("Update: %f usecs\n", cast(float)(Time.getUSecTime() - time));
962 
963 	writeEntityComponents(gEntityManager.getEntity(entity2));
964 
965 	entity = gEntityManager.addEntity(tmpl).id;
966 
967 	gEntityManager.begin();
968 	gEntityManager.update();
969 	gEntityManager.end();
970 
971 	//Entity* pp;// = gEntityManager.getEntity(entity.id);
972 	////writeln((cast(uint*) pp)[0 .. 14], " ", pp);
973 	writeEntityComponents(gEntityManager.getEntity(entity));
974 
975 	//writeln("Entity, its copy, and template, and default filled tempalte");
976 	gEntityManager.addEntity(tmpl);
977 	writeEntityComponents(gEntityManager.getEntity(entity));
978 	writeEntityComponents(gEntityManager.addEntityCopy(entity));
979 	EntityTemplate* copy_tempalte = gEntityManager.allocateTemplate(entity);
980 	writeEntityComponents(gEntityManager.addEntity(copy_tempalte));
981 	EntityTemplate* copy_default_tempalte = gEntityManager.allocateTemplate(entity, true);
982 	writeEntityComponents(gEntityManager.addEntity(copy_default_tempalte));
983 
984 	gEntityManager.addComponents(entity, TestComp4());
985 	gEntityManager.addComponents(entity, TestComp3());
986 
987 	gEntityManager.begin();
988 	gEntityManager.update();
989 	gEntityManager.end();
990 
991 	writeEntityComponents(gEntityManager.getEntity(entity));
992 
993 	gEntityManager.removeComponents!(TestComp)(entity);
994 	gEntityManager.addComponents(entity, TestComp());
995 	gEntityManager.addComponents(entity, TestComp5());
996 
997 	gEntityManager.begin();
998 	gEntityManager.update();
999 	gEntityManager.update("fixed");
1000 	gEntityManager.end();
1001 
1002 	gEntityManager.removeComponents!(TestComp4)(entity);
1003 
1004 	gEntityManager.commit();
1005 
1006 	System* sys = gEntityManager.getSystem(becsID!TestSystem2);
1007 
1008 	ExternalUpdateCallTest external_update_test;
1009 
1010 	gEntityManager.callEntitiesFunction!TestSystem2(&external_update_test.update);
1011 
1012 	printf("pre end\n");
1013 
1014 	writeEntityComponents(gEntityManager.getEntity(entity));
1015 	//import std.stdio;
1016 	////writeln((cast(uint*)tmpl.info.first_block)[0..48]);
1017 	gEntityManager.freeTemplate(tmpl_empty);
1018 	gEntityManager.freeTemplate(tmpl);
1019 	gEntityManager.freeTemplate(tmpl2);
1020 	gEntityManager.freeTemplate(copy_tempalte);
1021 	gEntityManager.freeTemplate(copy_default_tempalte);
1022 	EntityManager.destroy();
1023 
1024 	Mallocator.dispose(idss);
1025 
1026 	printf("end\n"); //*/
1027 
1028 	return 0;
1029 }