Demos #10

Merged
Mergul merged 39 commits from Demos into master 2020-05-28 18:48:45 +02:00
4 changed files with 385 additions and 20 deletions
Showing only changes of commit f6e7af1014 - Show all commits

View file

@ -45,6 +45,28 @@ struct Entity
uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof()); uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof());
return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof); return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof);
} }
EntityMeta getMeta()
{
EntityMeta meta;
meta.block = gEM.getMetaData(&this);
static if (EntityID.sizeof == 8)
meta.index = cast(ushort)((cast(void*)&this - meta.block.dataBegin()) >> 3);
else
meta.index = cast(ushort)((cast(void*)&this - meta.block.dataBegin()) / EntityID.sizeof());
return meta;
}
}
struct EntityMeta
{
EntityManager.EntitiesBlock* block;
ushort index;
T* getComponent(T)() const
{
return cast(T*)(cast(void*)block + block.type_info.deltas[T.component_id] + index * T.sizeof);
}
} }
/************************************************************************************************************************ /************************************************************************************************************************

128
tests/access_perf.d Normal file
View file

@ -0,0 +1,128 @@
module tests.access_perf;
import tests.runner;
import bubel.ecs.core;
import bubel.ecs.manager;
import bubel.ecs.entity;
import std.array : staticArray;
import core.stdc.stdio;
struct CLong
{
mixin ECS.Component;
alias value this;
long value = 10;
}
struct CInt
{
mixin ECS.Component;
alias value this;
int value = 10;
}
struct CUInt
{
mixin ECS.Component;
alias value this;
uint value = 12;
}
struct CBig
{
mixin ECS.Component;
uint[32] data;
}
EntityTemplate* tmpl;
void beforeEveryTest()
{
gEM.initialize(0);
gEM.beginRegister();
gEM.registerComponent!CLong;
gEM.registerComponent!CInt;
gEM.registerComponent!CUInt;
gEM.registerComponent!CBig;
gEM.endRegister();
tmpl = gEM.allocateTemplate([CLong.component_id, CInt.component_id, CUInt.component_id, CBig.component_id].staticArray);
foreach(i; 0 .. 100_000)gEM.addEntity(tmpl);
}
void afterEveryTest()
{
if(tmpl)gEM.freeTemplate(tmpl);
tmpl = null;
gEM.destroy();
}
@("DirectAccess100k1comp")
unittest
{
foreach(i;0..25000)
{
Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
CUInt* comp1 = entity.getComponent!CUInt;
comp1.value = 4;
}
}
@("DirectAccess100k4comp")
unittest
{
foreach(i;0..25000)
{
Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
CUInt* comp1 = entity.getComponent!CUInt;
comp1.value = 4;
CInt* comp2 = entity.getComponent!CInt;
comp2.value = 3;
CLong* comp3 = entity.getComponent!CLong;
comp3.value = 1;
CBig* comp4 = entity.getComponent!CBig;
comp4.data[0] = 2;
}
}
@("DirectAccess100k1compWithMeta")
unittest
{
foreach(i;0..25000)
{
Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
EntityMeta meta = entity.getMeta();
CUInt* comp1 = meta.getComponent!CUInt;
comp1.value = 4;
}
}
@("DirectAccess100k4compWithMeta")
unittest
{
foreach(i;0..25000)
{
Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
EntityMeta meta = entity.getMeta();
CUInt* comp1 = meta.getComponent!CUInt;
comp1.value = 4;
CInt* comp2 = meta.getComponent!CInt;
comp2.value = 3;
CLong* comp3 = meta.getComponent!CLong;
comp3.value = 1;
CBig* comp4 = meta.getComponent!CBig;
comp4.data[0] = 2;
}
}

178
tests/perf.d Normal file
View file

@ -0,0 +1,178 @@
module tests.perf;
import tests.runner;
import bubel.ecs.core;
import bubel.ecs.manager;
import bubel.ecs.entity;
import std.array : staticArray;
import core.stdc.stdio;
struct CLong
{
mixin ECS.Component;
alias value this;
long value = 10;
}
struct CShort
{
mixin ECS.Component;
alias value this;
short value = 12;
}
struct CInt
{
mixin ECS.Component;
alias value this;
int value = 10;
}
struct CUInt
{
mixin ECS.Component;
alias value this;
uint value = 12;
}
struct CBig
{
mixin ECS.Component;
uint[32] data;
}
EntityTemplate* tmpl;
void beforeEveryTest()
{
gEM.initialize(0);
gEM.beginRegister();
gEM.registerComponent!CLong;
gEM.registerComponent!CShort;
gEM.registerComponent!CInt;
gEM.registerComponent!CUInt;
gEM.registerComponent!CBig;
gEM.endRegister();
tmpl = null;
}
void afterEveryTest()
{
if(tmpl)gEM.freeTemplate(tmpl);
tmpl = null;
gEM.destroy();
}
void smallTmpl()
{
tmpl = gEM.allocateTemplate([CShort.component_id].staticArray);
}
void bigTmpl()
{
tmpl = gEM.allocateTemplate([CBig.component_id].staticArray);
}
void multiSmallTmpl()
{
tmpl = gEM.allocateTemplate([CShort.component_id, CLong.component_id, CInt.component_id, CUInt.component_id].staticArray);
}
void multiBigTmpl()
{
tmpl = gEM.allocateTemplate([CLong.component_id, CInt.component_id, CUInt.component_id, CBig.component_id].staticArray);
}
@("AddEntities100k1comp2b") @(before, &smallTmpl)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k1comp128b") @(before, &bigTmpl)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k4comp18b") @(before, &multiSmallTmpl)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k4comp144b") @(before, &multiBigTmpl)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
void allocDealloc100k()
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
gEM.commit();
foreach(i; 0..100_000)gEM.removeEntity(EntityID(i + 1,0));
gEM.commit();
}
void smallTmplPreAlloc()
{
tmpl = gEM.allocateTemplate([CShort.component_id].staticArray);
allocDealloc100k();
}
void bigTmplPreAlloc()
{
tmpl = gEM.allocateTemplate([CBig.component_id].staticArray);
allocDealloc100k();
}
void multiSmallTmplPreAlloc()
{
tmpl = gEM.allocateTemplate([CShort.component_id, CLong.component_id, CInt.component_id, CUInt.component_id].staticArray);
allocDealloc100k();
}
void multiBigTmplPreAlloc()
{
tmpl = gEM.allocateTemplate([CLong.component_id, CInt.component_id, CUInt.component_id, CBig.component_id].staticArray);
allocDealloc100k();
}
@("AddEntities100k1comp2bPreAlloc") @(before, &smallTmplPreAlloc)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k1comp128bPreAlloc") @(before, &bigTmplPreAlloc)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k4comp18bPreAlloc") @(before, &multiSmallTmplPreAlloc)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}
@("AddEntities100k4comp144bPreAlloc") @(before, &multiBigTmplPreAlloc)
unittest
{
foreach(i; 0..100_000)gEM.addEntity(tmpl);
}

View file

@ -9,8 +9,19 @@ import bubel.ecs.vector;
import bubel.ecs.simple_vector; import bubel.ecs.simple_vector;
import bubel.ecs.std; import bubel.ecs.std;
import std.traits;
import tests.time; import tests.time;
version (LDC)
{
import ldc.attributes;
}
else
{
enum optStrategy = 0;
}
enum int ASSERTED = 123; enum int ASSERTED = 123;
enum string OUT_FILE = "test_report.xml"; enum string OUT_FILE = "test_report.xml";
@ -124,23 +135,44 @@ struct TestRunner(Args...)
write("</testsuites>"); write("</testsuites>");
} }
@(optStrategy,"none")
void runTests(string[] include = null, string[] exclude = null) void runTests(string[] include = null, string[] exclude = null)
{ {
foreach (i, module_; Args) foreach (i, module_; Args)
{ {
TestSuite* suite = &suites[i]; TestSuite* suite = &suites[i];
suite.name = module_.stringof; suite.name = module_.stringof;
void function() before;
void function() after;
foreach (index, unittest_; __traits(getUnitTests, module_)) foreach (index, unittest_; __traits(getUnitTests, module_))
{ {
enum attributes = __traits(getAttributes, unittest_); enum attributes = __traits(getAttributes, unittest_);
static if (attributes.length != 0) static if (attributes.length != 0)
{
foreach(attr_id, attr; attributes)
{
static if(isFunctionPointer!(attr)){}
else static if(attr == "_tr_before")
{
static assert(attr_id+1 < attributes.length);
enum attr2 = attributes[attr_id + 1];
//static assert(__traits(hasMember, module_, attr2));
//alias func = __traits(getMember, module_, attr2);
//attr2();
before = attr2;
//static assert(is(typeof(__traits(getMember, module_, attr2)) == void function()));
}
else
{ {
if (include.length > 0) if (include.length > 0)
{ {
bool matched = false; bool matched = false;
foreach (str; include) foreach (str; include)
{ {
if (match(str, attributes[0])) if (match(str, attr))
{ {
matched = true; matched = true;
break; break;
@ -149,7 +181,7 @@ struct TestRunner(Args...)
foreach (str; exclude) foreach (str; exclude)
{ {
if (match(str, attributes[0])) if (match(str, attr))
{ {
matched = false; matched = false;
break; break;
@ -163,6 +195,8 @@ struct TestRunner(Args...)
} }
} }
} }
}
}
else if (include.length > 0) else if (include.length > 0)
{ {
suite.skipped++; suite.skipped++;
@ -178,6 +212,7 @@ struct TestRunner(Args...)
static if (__traits(hasMember, module_, "beforeEveryTest")) static if (__traits(hasMember, module_, "beforeEveryTest"))
module_.beforeEveryTest(); module_.beforeEveryTest();
if(before)before();
version(D_BetterC) version(D_BetterC)
{ {
@ -318,6 +353,8 @@ version (notBetterC)
version (D_Coverage) extern (C) void dmd_coverDestPath(string path); version (D_Coverage) extern (C) void dmd_coverDestPath(string path);
} }
enum before = "_tr_before";
void extractStrings(ref Vector!string container, string str) void extractStrings(ref Vector!string container, string str)
{ {
uint s = 0; uint s = 0;
@ -383,7 +420,7 @@ extern (C) int main(int argc, char** args)
} }
} }
TestRunner!(tests.runner, tests.id_manager, tests.vector, tests.basic) runner; TestRunner!(tests.id_manager, tests.vector, tests.basic, tests.perf, tests.access_perf) runner;
runner.runTests(include[], exclude[]); runner.runTests(include[], exclude[]);