51 Commits

Author SHA1 Message Date
2903b077fe Merge pull request #24 from BlackMATov/dev
Dev
2025-09-26 17:30:35 +07:00
BlackMATov
d3b14a6741 v1.3.0 2025-09-26 17:27:49 +07:00
BlackMATov
fdf5a03a02 improve performance of builders that are used for spawning multiple times 2025-09-26 17:21:50 +07:00
BlackMATov
9221da6ea7 slightly improve required fragments perf 2025-09-24 18:16:01 +07:00
BlackMATov
0aa57f6b5b benchmarks refactoring 2 2025-09-24 00:51:25 +07:00
BlackMATov
7e38e43d7c benchmarks refactoring 2025-09-23 17:37:29 +07:00
BlackMATov
b1b627b677 improve perf of cloning prefabs with many unique fragments 2025-09-23 07:53:11 +07:00
BlackMATov
281866cf6e set/assign hooks are not invoked for tags on override operations anymore 2025-09-23 07:24:26 +07:00
BlackMATov
4ad7fec26d update readme 2025-09-23 05:05:30 +07:00
BlackMATov
f15118be05 the new evolved.locate public function
ref: #23
2025-09-23 04:58:10 +07:00
BlackMATov
964ea45f48 use xpcall to process systems 2025-09-22 21:27:57 +07:00
BlackMATov
b2c08e1127 cancel deferring ops in systems on error 2025-09-22 05:51:21 +07:00
BlackMATov
2250bd64ce the new evolved.cancel public function 2025-09-22 02:34:37 +07:00
BlackMATov
e564be46fb collect garbage from old bytecode 2025-09-22 01:56:08 +07:00
BlackMATov
521ad94278 the internal garbage collector now collects more garbage 2025-09-20 03:11:12 +07:00
BlackMATov
7f6909e48c remove some unused code about pinned chunks 2025-09-20 01:53:29 +07:00
BlackMATov
ec745f6ad7 Merge branch 'feature/schemes' into dev 2025-09-19 19:51:02 +07:00
7b6ac89c8a Merge pull request #21 from BlackMATov/dev
Dev
2025-09-12 05:30:07 +07:00
6bf13890ef Merge pull request #14 from BlackMATov/dev
Dev
2025-06-06 21:28:17 +07:00
db191b805f Merge pull request #13 from BlackMATov/dev
Dev
2025-05-23 20:07:43 +07:00
5ab963022c Merge pull request #12 from BlackMATov/dev
Dev
2025-05-21 20:48:59 +07:00
7de95207d6 Merge pull request #11 from BlackMATov/dev
Dev
2025-05-21 17:34:13 +07:00
4d3b909efb Merge pull request #10 from BlackMATov/dev
Dev
2025-05-21 06:20:38 +07:00
52b3cbeb20 Merge pull request #9 from BlackMATov/dev
Dev
2025-05-21 03:38:16 +07:00
fec193f4f0 Merge pull request #8 from BlackMATov/dev
Dev
2025-05-21 02:11:39 +07:00
e672b0291a Merge pull request #7 from BlackMATov/dev
Dev
2025-05-02 07:28:38 +07:00
4624f2e603 Merge pull request #6 from BlackMATov/dev
Dev
2025-04-30 23:47:13 +07:00
c25769f64f Merge pull request #5 from BlackMATov/dev
Dev
2025-04-19 18:40:25 +07:00
d7274765cb Merge pull request #4 from BlackMATov/dev
Dev
2025-04-09 03:04:19 +07:00
ef033e7a0c Merge pull request #3 from BlackMATov/dev
Dev
2025-04-09 00:58:14 +07:00
3638dedca5 Merge pull request #2 from BlackMATov/dev
Dev
2025-04-06 21:27:33 +07:00
d025ea039b Merge pull request #1 from BlackMATov/dev
Dev
2025-04-05 02:12:18 +07:00
BlackMATov
6c0df71f17 Merge branch 'dev' 2025-03-27 15:36:58 +07:00
BlackMATov
730bffc3ad Merge branch 'dev' 2025-03-19 06:52:10 +07:00
BlackMATov
4bbd7ee60a Merge branch 'dev' 2025-03-18 07:08:27 +07:00
BlackMATov
79aecc8db3 Merge branch 'dev' 2025-03-17 00:23:36 +07:00
BlackMATov
b803faea63 Merge branch 'dev' 2025-03-16 07:46:26 +07:00
BlackMATov
722eda0b9b Merge branch 'dev' 2025-03-16 02:06:17 +07:00
BlackMATov
c6def51830 Merge branch 'dev' 2025-03-10 08:14:38 +07:00
BlackMATov
65312f79dd Merge branch 'dev' 2025-03-08 06:07:06 +07:00
BlackMATov
9877e41705 Merge branch 'dev' 2025-03-02 12:09:33 +07:00
BlackMATov
3b8367d5c4 Merge branch 'dev' 2025-02-24 06:06:26 +07:00
BlackMATov
419a6b6c45 Merge branch 'dev' 2025-02-23 03:54:56 +07:00
BlackMATov
368b50770c Merge branch 'dev' 2025-02-22 00:31:27 +07:00
BlackMATov
0d49802235 Merge branch 'dev' 2025-02-08 04:52:56 +07:00
BlackMATov
f096d747f3 Merge branch 'dev' 2025-01-31 22:14:13 +07:00
BlackMATov
4d88063c10 Merge branch 'dev' 2025-01-31 12:51:30 +07:00
BlackMATov
bf135534c0 Merge branch 'dev' 2025-01-25 08:37:55 +07:00
BlackMATov
177ea7f180 Merge branch 'dev' 2025-01-21 10:52:19 +07:00
BlackMATov
b98b5f9c42 Merge branch 'dev' 2025-01-18 01:39:27 +07:00
BlackMATov
c7120e8608 opt: get chunk by fragments without sorting 2025-01-16 06:42:03 +07:00
18 changed files with 1817 additions and 1586 deletions

View File

@@ -8,7 +8,6 @@
"markdown.extension.toc.levels": "2..6",
"markdown.extension.toc.omittedFromToc": {
"README.md": [
"# Changelog",
"# API Reference"
]
}

127
README.md
View File

@@ -31,6 +31,7 @@
- [Traits](#traits)
- [Singletons](#singletons)
- [Chunks](#chunks)
- [Entity Location](#entity-location)
- [Structural Changes](#structural-changes)
- [Spawning Entities](#spawning-entities)
- [Entity Builders](#entity-builders)
@@ -57,6 +58,11 @@
- [Classes](#classes)
- [Chunk](#chunk)
- [Builder](#builder)
- [Changelog](#changelog)
- [v1.3.0](#v130)
- [v1.2.0](#v120)
- [v1.1.0](#v110)
- [v1.0.0](#v100)
- [License](#license)
## Introduction
@@ -360,6 +366,43 @@ end
-- Entity: 1048603, Health: 75, Stamina: 40
```
#### Entity Location
Sometimes it is useful to know which chunk a specific entity is in and its position within that chunk. The [`evolved.locate`](#evolvedlocate) function provides this information.
```lua
---@param entity evolved.entity
---@return evolved.chunk? chunk
---@return integer place
function evolved.locate(entity) end
```
This function takes an entity and returns the chunk that contains it and the entitys position (index) within that chunk. If the entity is not alive or is empty, the function returns `nil` for the chunk and `0` for the place.
This is low-level functionality that you will rarely need. However, it can be useful in specific cases. For example, when you need to modify an entitys component directly to avoid unnecessary [Deferred Operations](#deferred-operations) or [Fragment Hooks](#fragment-hooks), instead of using a higher-level function like [`evolved.set`](#evolvedset).
```lua
local evolved = require 'evolved'
local health, stamina = evolved.id(2)
local player = evolved.id()
evolved.set(player, health, 100)
evolved.set(player, stamina, 50)
local player_chunk, player_place = evolved.locate(player)
local health_components = player_chunk:components(health)
local stamina_components = player_chunk:components(stamina)
health_components[player_place] = 75
stamina_components[player_place] = 42
```
> [!WARNING]
> Do not use [`evolved.locate`](#evolvedlocate) to manipulate components directly unless you fully understand what you are doing. Because it is low-level functionality, incorrect use can lead to inconsistencies, as it bypasses the librarys safety checks and hook mechanisms. Use it only when you are certain it is safe and necessary.
### Structural Changes
Every time we insert or remove a fragment from an entity, the entity will be migrated to a new chunk. This is done automatically by the library, of course. However, you should be aware of this because it can affect performance, especially if you have many fragments on the entity. This is called a `structural change`.
@@ -599,6 +642,9 @@ function evolved.defer() end
---@return boolean committed
function evolved.commit() end
---@return boolean cancelled
function evolved.cancel() end
```
The [`evolved.defer`](#evolveddefer) function starts a deferred scope. This means that all changes made inside the scope will be queued and applied after leaving the scope. The [`evolved.commit`](#evolvedcommit) function closes the last deferred scope and applies all queued changes. These functions can be nested, so you can start a new deferred scope inside an existing one. The [`evolved.commit`](#evolvedcommit) function will apply all queued changes only when the last deferred scope is closed.
@@ -629,6 +675,34 @@ evolved.commit()
assert(not evolved.has(player, poisoned))
```
The [`evolved.cancel`](#evolvedcancel) function can be used to cancel all queued changes in the current deferred scope. This is useful if you want to discard all changes made inside the scope and revert to the previous state on an error or some other condition.
```lua
local evolved = require 'evolved'
local health, poisoned = evolved.id(2)
local player = evolved.builder()
:set(health, 100)
:set(poisoned, true)
:spawn()
-- start a deferred scope
evolved.defer()
-- this removal will be queued, not applied immediately
evolved.remove(player, poisoned)
-- the player still has the poisoned fragment inside the deferred scope
assert(evolved.has(player, poisoned))
-- cancel the deferred operations
evolved.cancel()
-- the poisoned fragment is still there
assert(evolved.has(player, poisoned))
```
#### Batch Operations
The library provides a set of functions for batch operations. These functions are used to perform modifying operations on multiple chunks at once. This is very useful for performance reasons.
@@ -839,6 +913,9 @@ evolved.set(player, health, 200) -- prints "health set to 200"
Use [`evolved.ON_SET`](#evolvedon_set) for callbacks on fragment insert or override, [`evolved.ON_ASSIGN`](#evolvedon_assign) for overrides, and [`evolved.ON_INSERT`](#evolvedon_insert)/[`evolved.ON_REMOVE`](#evolvedon_remove) for insertions or removals.
> [!NOTE]
> Because fragments marked with [`evolved.TAG`](#evolvedtag) (also called [Fragment Tags](#fragment-tags)) have no components, their [`evolved.ON_SET`](#evolvedon_set) hooks are invoked only when the tag is inserted, not when it is overridden, as there is nothing to override. Their [`evolved.ON_ASSIGN`](#evolvedon_assign) hooks are never invoked for such tags for the same reason.
#### Unique Fragments
Some fragments should not be cloned when cloning entities. For example, `evolved.lua` has a special fragment called `evolved.PREFAB`, which marks entities used as sources for cloning. This fragment should not be present on the cloned entities. To prevent a fragment from being cloned, mark it as unique using the [`evolved.UNIQUE`](#evolvedunique) fragment trait. This ensures the fragment will not be copied when cloning entities.
@@ -1040,7 +1117,7 @@ execute :: {chunk, entity[], integer}
prologue :: {}
epilogue :: {}
set_hook :: {entity, fragment, component, component?}
set_hook :: {entity, fragment, component, component}
assign_hook :: {entity, fragment, component, component}
insert_hook :: {entity, fragment, component}
remove_hook :: {entity, fragment, component}
@@ -1101,6 +1178,7 @@ unpack :: id -> integer, integer
defer :: boolean
commit :: boolean
cancel :: boolean
spawn :: <fragment, component>? -> entity
multi_spawn :: integer, <fragment, component>? -> entity[]
@@ -1135,6 +1213,8 @@ batch_destroy :: query... -> ()
each :: entity -> {each_state? -> fragment?, component?}, each_state?
execute :: query -> {execute_state? -> chunk?, entity[]?, integer?}, execute_state?
locate :: entity -> chunk?, integer
process :: system... -> ()
debug_mode :: boolean -> ()
@@ -1198,7 +1278,7 @@ builder_mt:include :: fragment... -> builder
builder_mt:exclude :: fragment... -> builder
builder_mt:require :: fragment... -> builder
builder_mt:on_set :: {entity, fragment, component, component?} -> builder
builder_mt:on_set :: {entity, fragment, component, component} -> builder
builder_mt:on_assign :: {entity, fragment, component, component} -> builder
builder_mt:on_insert :: {entity, fragment, component} -> builder
builder_mt:on_remove :: {entity, fragment} -> builder
@@ -1214,31 +1294,37 @@ builder_mt:epilogue :: {} -> builder
builder_mt:destruction_policy :: id -> builder
```
## License
## Changelog
`evolved.lua` is licensed under the [MIT License][license]. For more details, see the [LICENSE.md](./LICENSE.md) file in the repository.
### v1.3.0
# Changelog
- Added the new [`evolved.cancel`](#evolvedcancel) function
- Added the new [`evolved.locate`](#evolvedlocate) function
- The internal garbage collector now collects more garbage
- Improved system processing debugging experience with stack traces on errors
- [`SET/ASSIGN hooks`](#fragment-hooks) are not invoked for tags on override operations anymore
- Improved performance of cloning prefabs with many [`Unique Fragments`](#unique-fragments)
- Improved performance of builders that are used for spawning multiple times
## vX.X.X
- Nothing yet, stay tuned!
## v1.2.0
### v1.2.0
- Added the new [`evolved.name`](#evolvedname-1) function
- Added the new [`evolved.multi_spawn`](#evolvedmulti_spawn) and [`evolved.multi_clone`](#evolvedmulti_clone) functions
- Added the new [`evolved.INTERNAL`](#evolvedinternal) fragment trait
## v1.1.0
### v1.1.0
- [`Systems`](#systems) can be queries themselves now
- Added the new [`evolved.REQUIRES`](#evolvedrequires) fragment trait
## v1.0.0
### v1.0.0
- Initial release
## License
`evolved.lua` is licensed under the [MIT License][license]. For more details, see the [LICENSE.md](./LICENSE.md) file in the repository.
# API Reference
## Predefs
@@ -1345,6 +1431,13 @@ function evolved.defer() end
function evolved.commit() end
```
### `evolved.cancel`
```lua
---@return boolean cancelled
function evolved.cancel() end
```
### `evolved.spawn`
```lua
@@ -1557,6 +1650,16 @@ function evolved.each(entity) end
function evolved.execute(query) end
```
### `evolved.locate`
```lua
---@param entity evolved.entity
---@return evolved.chunk? chunk
---@return integer place
---@nodiscard
function evolved.locate(entity) end
```
### `evolved.process`
```lua

View File

@@ -2,10 +2,7 @@
## Backlog
- Improve the performance of required fragments by caching first-level required chunks.
- Improve the performance of builders that are used multiple times by caching hint chunks.
- Queries can cache major chunks to avoid finding them every time.
- Add a function to shrink storages to free unused memory.
- observers and events
- add INDEX fragment trait
- use compact prefix-tree for chunks
@@ -15,4 +12,7 @@
- We can return deferred status from modifying operations and spawn/clone methods.
- Should we make one builder:build method instead of :spawn and :clone?
- Should we cache the result of without_unique_fragments to clone faster?
## Known Issues
- Required fragments are slower than they should be

View File

@@ -1,19 +1,21 @@
require 'develop.samples.systems'
require 'develop.testing.cancel_tests'
require 'develop.testing.locate_tests'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.multi_clone_bmarks'
require 'develop.benchmarks.multi_spawn_bmarks'
require 'develop.benchmarks.clone_bmarks'
require 'develop.benchmarks.common_bmarks'
require 'develop.benchmarks.migration_bmarks'
require 'develop.benchmarks.process_bmarks'
require 'develop.benchmarks.spawn_bmarks'
require 'develop.benchmarks.table_bmarks'
require 'develop.untests'
require 'develop.unbench'
require 'develop.usbench'
local basics = require 'develop.basics'
print '----------------------------------------'

View File

@@ -0,0 +1,166 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R3] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R5] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,340 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
local tiny = require 'develop.3rdparty.tiny'
evo.debug_mode(false)
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Entity Cycle | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0 })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) world:addEntity({ b = e.a }) end
A.postProcess = function(_) world:refresh() end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) world:removeEntity(e) end
B.postProcess = function(_) world:refresh() end
world:addSystem(A)
world:addSystem(B)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Entity Cycle | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local query_a = evo.builder():set(world):include(a):spawn()
local query_b = evo.builder():set(world):include(b):spawn()
local prefab_a = evo.builder():prefab():set(world):set(a, 0):spawn()
local prefab_b = evo.builder():prefab():set(world):set(b, 0):spawn()
evo.multi_clone(N, prefab_a)
evo.builder()
:set(world):group(world):query(query_a)
:execute(function(chunk, _, entity_count)
local as = chunk:components(a)
local entity_bs = evo.multi_clone(entity_count, prefab_b)
for i = 1, entity_count do evo.set(entity_bs[i], b, as[i]) end
end):spawn()
evo.builder()
:set(world):group(world):query(query_b)
:prologue(function()
evo.batch_destroy(query_b)
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Simple Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0, b = 0 })
world:addEntity({ a = 0, b = 0, c = 0 })
world:addEntity({ a = 0, b = 0, c = 0, d = 0 })
world:addEntity({ a = 0, b = 0, c = 0, e = 0 })
end
local AB = tiny.processingSystem()
AB.filter = tiny.requireAll('a', 'b')
AB.process = function(_, e) e.a, e.b = e.b, e.a end
local CD = tiny.processingSystem()
CD.filter = tiny.requireAll('c', 'd')
CD.process = function(_, e) e.c, e.d = e.d, e.c end
local CE = tiny.processingSystem()
CE.filter = tiny.requireAll('c', 'e')
CE.process = function(_, e) e.c, e.e = e.e, e.c end
world:addSystem(AB)
world:addSystem(CD)
world:addSystem(CE)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Simple Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local c = evo.builder():set(world):spawn()
local d = evo.builder():set(world):spawn()
local e = evo.builder():set(world):spawn()
local query_ab = evo.builder():set(world):include(a, b):spawn()
local query_cd = evo.builder():set(world):include(c, d):spawn()
local query_ce = evo.builder():set(world):include(c, e):spawn()
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_ab)
:execute(function(chunk, _, entity_count)
local as, bs = chunk:components(a, b)
for i = 1, entity_count do as[i], bs[i] = bs[i], as[i] end
end):spawn()
evo.builder()
:set(world):group(world):query(query_cd)
:execute(function(chunk, _, entity_count)
local cs, ds = chunk:components(c, d)
for i = 1, entity_count do cs[i], ds[i] = ds[i], cs[i] end
end):spawn()
evo.builder()
:set(world):group(world):query(query_ce)
:execute(function(chunk, _, entity_count)
local cs, es = chunk:components(c, e)
for i = 1, entity_count do cs[i], es[i] = es[i], cs[i] end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Packed Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0, b = 0, c = 0, d = 0, e = 0 })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) e.a = e.a * 2 end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) e.b = e.b * 2 end
local C = tiny.processingSystem()
C.filter = tiny.requireAll('c')
C.process = function(_, e) e.c = e.c * 2 end
local D = tiny.processingSystem()
D.filter = tiny.requireAll('d')
D.process = function(_, e) e.d = e.d * 2 end
local E = tiny.processingSystem()
E.filter = tiny.requireAll('e')
E.process = function(_, e) e.e = e.e * 2 end
world:addSystem(A)
world:addSystem(B)
world:addSystem(C)
world:addSystem(D)
world:addSystem(E)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Packed Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local c = evo.builder():set(world):spawn()
local d = evo.builder():set(world):spawn()
local e = evo.builder():set(world):spawn()
local query_a = evo.builder():set(world):include(a):spawn()
local query_b = evo.builder():set(world):include(b):spawn()
local query_c = evo.builder():set(world):include(c):spawn()
local query_d = evo.builder():set(world):include(d):spawn()
local query_e = evo.builder():set(world):include(e):spawn()
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_a)
:execute(function(chunk, _, entity_count)
local as = chunk:components(a)
for i = 1, entity_count do as[i] = as[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_b)
:execute(function(chunk, _, entity_count)
local bs = chunk:components(b)
for i = 1, entity_count do bs[i] = bs[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_c)
:execute(function(chunk, _, entity_count)
local cs = chunk:components(c)
for i = 1, entity_count do cs[i] = cs[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_d)
:execute(function(chunk, _, entity_count)
local ds = chunk:components(d)
for i = 1, entity_count do ds[i] = ds[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_e)
:execute(function(chunk, _, entity_count)
local es = chunk:components(e)
for i = 1, entity_count do es[i] = es[i] * 2 end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Fragmented Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
---@type string[]
local chars = {}
for i = 1, 26 do
chars[i] = string.char(string.byte('a') + i - 1)
end
for i, char in ipairs(chars) do
for _ = 1, N do
world:addEntity({ [char] = i, data = i })
end
end
local Data = tiny.processingSystem()
Data.filter = tiny.requireAll('data')
Data.process = function(_, e) e.data = e.data * 2 end
local Last = tiny.processingSystem()
Last.filter = tiny.requireAll('z')
Last.process = function(_, e) e.z = e.z * 2 end
world:addSystem(Data)
world:addSystem(Last)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Fragmented Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local data = evo.spawn { [world] = true }
local chars = evo.multi_spawn(26, { [world] = true })
local query_data = evo.builder():set(world):include(data):spawn()
local query_z = evo.builder():set(world):include(chars[#chars]):spawn()
for i = 1, #chars do
evo.multi_spawn(N, { [world] = true, [chars[i]] = i, [data] = i })
end
evo.builder()
:set(world):group(world):query(query_data)
:execute(function(chunk, _, entity_count)
local datas = chunk:components(data)
for i = 1, entity_count do datas[i] = datas[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_z)
:execute(function(chunk, _, entity_count)
local zs = chunk:components(chars[#chars])
for i = 1, entity_count do zs[i] = zs[i] * 2 end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)

View File

@@ -0,0 +1,104 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 1 component', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
end
evo.commit()
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 3 components', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
end
evo.commit()
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 5 components', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
end
evo.commit()
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 1 component', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 3 components', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 5 components', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
end
evo.batch_destroy(Q1)
end)

View File

@@ -1,59 +0,0 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)

View File

@@ -1,59 +0,0 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,236 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [R3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [R5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(R3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(R5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R3] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R5] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,136 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables', N),
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate and Collect %d tables', N),
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
for i = 1, N do
tables[i] = nil
end
collectgarbage('collect')
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 1 component / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 3 components / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 5 components / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
e[F5] = true
tables[i] = e
end
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 1 component / SoA', N),
function(tables)
local fs1 = {}
for i = 1, N do
local e = {}
fs1[i] = true
tables[i] = e
end
tables[F1] = fs1
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 3 components / SoA', N),
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 5 components / SoA', N),
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
local fs5 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
fs4[i] = true
fs5[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
tables[F5] = fs5
end, function()
return {}
end)

View File

@@ -0,0 +1,105 @@
local evo = require 'evolved'
do
assert(evo.defer())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
local e, f = evo.id(2)
assert(evo.defer())
do
evo.set(e, f)
assert(not evo.has(e, f))
end
assert(evo.cancel())
assert(not evo.has(e, f))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.commit())
assert(evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.commit())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end

View File

@@ -0,0 +1,48 @@
local evo = require 'evolved'
do
local e1, e2, f1, f2 = evo.id(4)
do
local chunk, place = evo.locate(e1)
assert(chunk == nil and place == 0)
end
evo.set(e1, f1, 42)
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1) and place == 1)
assert(chunk:components(f1)[place] == 42)
chunk, place = evo.locate(e2)
assert(chunk == nil and place == 0)
end
evo.set(e1, f2, 'hello')
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 1)
assert(chunk:components(f1)[place] == 42)
assert(chunk:components(f2)[place] == 'hello')
chunk, place = evo.locate(e2)
assert(chunk == nil and place == 0)
end
evo.set(e2, f1, 84)
evo.set(e2, f2, 'world')
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 1)
assert(chunk:components(f1)[place] == 42)
assert(chunk:components(f2)[place] == 'hello')
chunk, place = evo.locate(e2)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 2)
assert(chunk:components(f1)[place] == 84)
assert(chunk:components(f2)[place] == 'world')
end
end

View File

@@ -1,860 +0,0 @@
local basics = require 'develop.basics'
basics.unload 'evolved'
local evo = require 'evolved'
local N = 1000
local B = evo.builder()
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
local R1 = evo.builder():require(F1):spawn()
local R2 = evo.builder():require(F1, F2):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R4 = evo.builder():require(F1, F2, F3, F4):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables', N),
---@param tables table[]
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
end, function()
return {}
end)
basics.describe_bench(string.format('create and collect %d tables', N),
---@param tables table[]
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
for i = 1, #tables do
tables[i] = nil
end
collectgarbage('collect')
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables with 1 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 2 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 3 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 4 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 5 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
e[F5] = true
tables[i] = e
end
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables with 1 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
for i = 1, N do
local e = {}
fs1[i] = true
tables[i] = e
end
tables[F1] = fs1
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 2 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 3 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 4 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
for i = 1, N do
local e = {}
fs1[i] = i
fs2[i] = i
fs3[i] = i
fs4[i] = i
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 5 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
local fs5 = {}
for i = 1, N do
local e = {}
fs1[i] = i
fs2[i] = i
fs3[i] = i
fs4[i] = i
fs5[i] = i
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
tables[F5] = fs5
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local destroy = evo.destroy
for i = 1, N do
local e = id()
entities[i] = e
end
for i = #entities, 1, -1 do
destroy(entities[i])
end
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 1 component', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
set(B, F4)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
set(B, F4)
set(B, F5)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R1] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R2] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R3] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R4] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R5] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R1] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R2] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R3] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R4] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R5] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)

View File

@@ -1525,7 +1525,7 @@ do
do
last_set_entity = 0
evo.set(e, f1, 41)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and not evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1539,13 +1539,13 @@ do
do
last_set_entity = 0
evo.set(e, f1, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
last_set_entity = 0
evo.set(e, f2, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1559,13 +1559,13 @@ do
do
last_set_entity = 0
evo.set(e, f1, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2) and evo.has(e, f3))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil and evo.get(e, f3) == 43)
last_set_entity = 0
evo.set(e, f2, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2) and evo.has(e, f3))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil and evo.get(e, f3) == 43)
@@ -1610,7 +1610,7 @@ do
last_assign_entity = 0
evo.set(e, f1)
assert(last_assign_entity == e)
assert(last_assign_entity == 0)
assert(evo.has(e, f1) and not evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1623,7 +1623,7 @@ do
last_assign_entity = 0
evo.set(e, f2, 44)
assert(last_assign_entity == e)
assert(last_assign_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -6373,3 +6373,79 @@ do
assert(evo.get(e, f) ~= v2_default)
end
end
do
local f1, f2 = evo.id(2)
local prefab = evo.builder():prefab():set(f1, 11):set(f2, 22):spawn()
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
evo.set(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(not evo.has(entity, f2) and evo.get(entity, f2) == nil)
end
evo.remove(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
evo.set(f1, evo.UNIQUE)
evo.set(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.empty(entity))
end
evo.remove(f1, evo.UNIQUE)
evo.remove(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
end
do
do
local f = evo.id()
local c = evo.chunk(f)
local b = evo.builder():set(f, 42)
evo.collect_garbage()
local e = b:spawn()
assert(evo.locate(e) ~= c)
assert(evo.locate(e) == evo.chunk(f))
end
do
local f = evo.id()
local c = evo.chunk(f)
local b = evo.builder():set(f, 42)
evo.collect_garbage()
local es = b:multi_spawn(5)
for i = 1, 5 do
assert(evo.locate(es[i]) ~= c)
assert(evo.locate(es[i]) == evo.chunk(f))
end
end
end
do
local ff, ft = evo.id(2)
local b = evo.builder():set(ff, false):set(ft, true)
assert(b:has_all() and not b:has_any())
assert(b:has(ff) and b:has(ft) and b:has_all(ff, ft) and b:has_any(ff, ft))
end

View File

@@ -1,374 +0,0 @@
local basics = require 'develop.basics'
basics.unload 'evolved'
local evo = require 'evolved'
local tiny = require 'develop.3rdparty.tiny'
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Entity Cycle: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) world:addEntity({ b = e.a }) end
A.postProcess = function(_) world:refresh() end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) world:removeEntity(e) end
B.postProcess = function(_) world:refresh() end
world:addSystem(A)
world:addSystem(B)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Entity Cycle (Defer): %d entities', N),
function(a, b, A, B)
evo.defer()
do
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
evo.set(evo.id(), b, as[i])
end
end
end
evo.commit()
evo.batch_destroy(B)
end, function()
local a, b = evo.id(2)
for i = 1, N do
evo.builder():set(a, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
return a, b, A, B
end, function(_, _, A, _)
evo.batch_destroy(A)
end)
basics.describe_bench(string.format('Evolved Entity Cycle (Manual): %d entities', N),
function(a, b, A, B)
local to_create = {}
local to_create_count = 0
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
to_create_count = to_create_count + 1
to_create[to_create_count] = as[i]
end
end
for i = 1, to_create_count do
local e = evo.id()
evo.set(e, b, to_create[i])
end
evo.batch_destroy(B)
end, function()
local a, b = evo.id(2)
for i = 1, N do
evo.builder():set(a, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
return a, b, A, B
end, function(_, _, A, _)
evo.batch_destroy(A)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Simple Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i, b = i })
world:addEntity({ a = i, b = i, c = i })
world:addEntity({ a = i, b = i, c = i, d = i })
world:addEntity({ a = i, b = i, c = i, e = i })
end
local AB = tiny.processingSystem()
AB.filter = tiny.requireAll('a', 'b')
AB.process = function(_, e) e.a, e.b = e.b, e.a end
local CD = tiny.processingSystem()
CD.filter = tiny.requireAll('c', 'd')
CD.process = function(_, e) e.c, e.d = e.d, e.c end
local CE = tiny.processingSystem()
CE.filter = tiny.requireAll('c', 'e')
CE.process = function(_, e) e.c, e.e = e.e, e.c end
world:addSystem(AB)
world:addSystem(CD)
world:addSystem(CE)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Simple Iteration: %d entities', N),
---@param a evolved.entity
---@param b evolved.entity
---@param c evolved.entity
---@param d evolved.entity
---@param e evolved.entity
---@param AB evolved.query
---@param CD evolved.query
---@param CE evolved.query
function(a, b, c, d, e, AB, CD, CE)
for chunk, _, entity_count in evo.execute(AB) do
local as, bs = chunk:components(a, b)
for i = 1, entity_count do
as[i], bs[i] = bs[i], as[i]
end
end
for chunk, _, entity_count in evo.execute(CD) do
local cs, ds = chunk:components(c, d)
for i = 1, entity_count do
cs[i], ds[i] = ds[i], cs[i]
end
end
for chunk, _, entity_count in evo.execute(CE) do
local cs, es = chunk:components(c, e)
for i = 1, entity_count do
cs[i], es[i] = es[i], cs[i]
end
end
end, function()
local a, b, c, d, e = evo.id(5)
for i = 1, N do
evo.builder():set(a, i):set(b, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):set(d, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):set(e, i):spawn()
end
local AB = evo.builder():include(a, b):spawn()
local CD = evo.builder():include(c, d):spawn()
local CE = evo.builder():include(c, e):spawn()
return a, b, c, d, e, AB, CD, CE
end, function(_, _, _, _, _, AB, CD, CE)
evo.batch_destroy(AB)
evo.batch_destroy(CD)
evo.batch_destroy(CE)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Packed Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i, b = i, c = i, d = i, e = i })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) e.a = e.a * 2 end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) e.b = e.b * 2 end
local C = tiny.processingSystem()
C.filter = tiny.requireAll('c')
C.process = function(_, e) e.c = e.c * 2 end
local D = tiny.processingSystem()
D.filter = tiny.requireAll('d')
D.process = function(_, e) e.d = e.d * 2 end
local E = tiny.processingSystem()
E.filter = tiny.requireAll('e')
E.process = function(_, e) e.e = e.e * 2 end
world:addSystem(A)
world:addSystem(B)
world:addSystem(C)
world:addSystem(D)
world:addSystem(E)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Packed Iteration: %d entities', N),
---@param a evolved.entity
---@param b evolved.entity
---@param c evolved.entity
---@param d evolved.entity
---@param e evolved.entity
---@param A evolved.query
---@param B evolved.query
---@param C evolved.query
---@param D evolved.query
---@param E evolved.query
function(a, b, c, d, e, A, B, C, D, E)
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
as[i] = as[i] * 2
end
end
for chunk, _, entity_count in evo.execute(B) do
local bs = chunk:components(b)
for i = 1, entity_count do
bs[i] = bs[i] * 2
end
end
for chunk, _, entity_count in evo.execute(C) do
local cs = chunk:components(c)
for i = 1, entity_count do
cs[i] = cs[i] * 2
end
end
for chunk, _, entity_count in evo.execute(D) do
local ds = chunk:components(d)
for i = 1, entity_count do
ds[i] = ds[i] * 2
end
end
for chunk, _, entity_count in evo.execute(E) do
local es = chunk:components(e)
for i = 1, entity_count do
es[i] = es[i] * 2
end
end
end, function()
local a, b, c, d, e = evo.id(5)
for i = 1, N do
evo.builder():set(a, i):set(b, i):set(c, i):set(d, i):set(e, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
local C = evo.builder():include(c):spawn()
local D = evo.builder():include(d):spawn()
local E = evo.builder():include(e):spawn()
return a, b, c, d, e, A, B, C, D, E
end, function(_, _, _, _, _, A, _, _, _, _)
evo.batch_destroy(A)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Fragmented Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
---@type string[]
local chars = {}
for i = 1, 26 do
chars[i] = string.char(string.byte('a') + i - 1)
end
for _, char in ipairs(chars) do
for i = 1, N do
world:addEntity({ [char] = i, data = i })
end
end
local Data = tiny.processingSystem()
Data.filter = tiny.requireAll('data')
Data.process = function(_, e) e.data = e.data * 2 end
local Last = tiny.processingSystem()
Last.filter = tiny.requireAll('z')
Last.process = function(_, e) e.z = e.z * 2 end
world:addSystem(Data)
world:addSystem(Last)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Fragmented Iteration: %d entities', N),
---@param data evolved.entity
---@param last evolved.entity
---@param Data evolved.query
---@param Last evolved.query
function(data, last, Data, Last)
for chunk, _, entity_count in evo.execute(Data) do
local ds = chunk:components(data)
for i = 1, entity_count do
ds[i] = ds[i] * 2
end
end
for chunk, _, entity_count in evo.execute(Last) do
local ls = chunk:components(last)
for i = 1, entity_count do
ls[i] = ls[i] * 2
end
end
end, function()
local data = evo.id()
---@type evolved.fragment[]
local chars = {}
for i = 1, 26 do
chars[i] = evo.id()
end
for _, char in ipairs(chars) do
for i = 1, N do
evo.builder():set(char, i):set(data, i):spawn()
end
end
local Data = evo.builder():include(data):spawn()
local Last = evo.builder():include(chars[#chars]):spawn()
return data, chars[#chars], Data, Last
end, function(_, _, Data, _)
evo.batch_destroy(Data)
end)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.3.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.3.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}