public void TestMillionEntitySystem() { const int size = 100_000; var gameWorld = new GameWorld(); var entities = new GameEntityHandle[size]; gameWorld.CreateEntityBulk(entities); var componentType = gameWorld.AsComponentType<IntComponent>(); for (var i = 0; i < size; i++) { gameWorld.AddComponent(entities[i], componentType); } var sw = new Stopwatch(); var lowest = TimeSpan.MaxValue; using var runner = new ThreadBatchRunner(1f); runner.StartPerformanceCriticalSection(); var query = new EntityQuery(gameWorld, new[] {componentType}); var system = new ArchetypeSystem<int>((in ReadOnlySpan<GameEntityHandle> entities, in SystemState<int> state) => { var accessor = new ComponentDataAccessor<IntComponent>(state.World); foreach (ref readonly var entity in entities) accessor[entity].Value++; }, query);
public void TestBulk() { var lowest = TimeSpan.MaxValue; var entities = new GameEntityHandle[entityCount]; for (var iteration = 0; iteration != 100; iteration++) { var world = new GameWorld(); var sw = new Stopwatch(); var componentType = world.AsComponentType <Component>(); sw.Start(); world.CreateEntityBulk(entities); for (var i = 0; i != entityCount; i++) { var ent = entities[i]; world.AddComponent(ent, componentType); world.RemoveEntity(ent); } sw.Stop(); if (lowest > sw.Elapsed) { lowest = sw.Elapsed; } } Console.WriteLine($"{lowest.TotalMilliseconds}ms"); }
public ComponentDataAccessor(GameWorld gameWorld, ComponentType original = default) { var componentType = original.Id == 0 ? gameWorld.AsComponentType(typeof(T)) : original; Source = ((SingleComponentBoard)gameWorld .Boards .ComponentType .ComponentBoardColumns[(int)componentType.Id]).AsSpan <T>(); Links = gameWorld.Boards.Entity.GetComponentColumn(componentType.Id); }
protected internal override void KeepAlive(Span <bool> keep, Span <GameEntity> resources) { var componentType = gameWorld.AsComponentType <TData>(); if (!(gameWorld.Boards.ComponentType.ComponentBoardColumns[(int)componentType.Id] is SingleComponentBoard componentBoard)) { return; } var dataSpan = componentBoard.AsSpan <TData>(); // It should be of the same length KeepAlive(keep, dataSpan, MemoryMarshal.Cast <GameEntity, GameResource <TResource> >(resources)); }
protected internal override void KeepAlive(Span <bool> keep, Span <GameEntity> resources) { var componentType = gameWorld.AsComponentType <TBuffer>(); if (!(gameWorld.Boards.ComponentType.ComponentBoardColumns[(int)componentType.Id] is BufferComponentBoard bufferComponentBoard)) { return; } var rawBufferSpan = bufferComponentBoard.AsSpan(); for (var i = 0; i != rawBufferSpan.Length; i++) { var buffer = new ComponentBuffer <TBuffer>(rawBufferSpan[i]); KeepAlive(keep, buffer.Span, MemoryMarshal.Cast <GameEntity, GameResource <TResource> >(resources)); } }