mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
372 lines
No EOL
8 KiB
Lua
372 lines
No EOL
8 KiB
Lua
local testkit = require("../testkit")
|
|
local jecs = require("../lib/init")
|
|
local ecr = require("../DevPackages/_Index/centau_ecr@0.8.0/ecr/src/ecr")
|
|
|
|
|
|
local BENCH, START = testkit.benchmark()
|
|
|
|
local function TITLE(title: string)
|
|
print()
|
|
print(testkit.color.white(title))
|
|
end
|
|
|
|
local N = 2^16-2
|
|
|
|
type i53 = number
|
|
|
|
do TITLE "create"
|
|
BENCH("entity", function()
|
|
local world = jecs.World.new()
|
|
for i = 1, START(N) do
|
|
world:entity()
|
|
end
|
|
end)
|
|
end
|
|
|
|
--- component benchmarks
|
|
|
|
--todo: perform the same benchmarks for multiple components.?
|
|
-- these kind of operations only support 1 component at a time, which is
|
|
-- a shame, especially for archetypes where moving components is expensive.
|
|
|
|
do TITLE "set"
|
|
BENCH("add 1 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
|
|
for i = 1, N do
|
|
entities[i] = world:entity()
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
world:set(entities[i], A, i)
|
|
end
|
|
end)
|
|
|
|
BENCH("change 1 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
local e = world:entity()
|
|
world:set(e, A, 1)
|
|
|
|
for i = 1, START(N) do
|
|
world:set(e, A, 2)
|
|
end
|
|
end)
|
|
|
|
end
|
|
|
|
do TITLE "remove"
|
|
BENCH("1 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
entities[i] = id
|
|
world:set(id, A, true)
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
world:remove(entities[i], A)
|
|
end
|
|
|
|
end)
|
|
end
|
|
|
|
do TITLE "get"
|
|
BENCH("1 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
entities[i] = id
|
|
world:set(id, A, true)
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
-- ? curious why the overhead is roughly 80 ns.
|
|
world:get(entities[i], A)
|
|
end
|
|
|
|
end)
|
|
|
|
BENCH("2 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
local B = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
entities[i] = id
|
|
world:set(id, A, true)
|
|
world:set(id, B, true)
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
world:get(entities[i], A, B)
|
|
end
|
|
|
|
end)
|
|
|
|
BENCH("3 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
local B = world:component()
|
|
local C = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
entities[i] = id
|
|
world:set(id, A, true)
|
|
world:set(id, B, true)
|
|
world:set(id, C, true)
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
world:get(entities[i], A, B, C)
|
|
end
|
|
|
|
end)
|
|
|
|
BENCH("4 component", function()
|
|
local world = jecs.World.new()
|
|
local entities = {}
|
|
|
|
local A = world:component()
|
|
local B = world:component()
|
|
local C = world:component()
|
|
local D = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
entities[i] = id
|
|
world:set(id, A, true)
|
|
world:set(id, B, true)
|
|
world:set(id, C, true)
|
|
world:set(id, D, true)
|
|
end
|
|
|
|
for i = 1, START(N) do
|
|
world:get(entities[i], A, B, C, D)
|
|
end
|
|
|
|
end)
|
|
end
|
|
|
|
do TITLE (testkit.color.white_underline("Jecs query"))
|
|
|
|
local function count(query: () -> ())
|
|
local n = 0
|
|
for _ in query do
|
|
n += 1
|
|
end
|
|
return n
|
|
end
|
|
|
|
local function flip()
|
|
return math.random() > 0.5
|
|
end
|
|
|
|
local function view_bench(
|
|
world: jecs.World,
|
|
A: i53, B: i53, C: i53, D: i53, E: i53, F: i53, G: i53, H: i53, I: i53
|
|
)
|
|
|
|
BENCH("1 component", function()
|
|
START(count(world:query(A)))
|
|
for _ in world:query(A) do end
|
|
end)
|
|
|
|
BENCH("2 component", function()
|
|
START(count(world:query(A, B)))
|
|
for _ in world:query(A, B) do end
|
|
end)
|
|
|
|
BENCH("4 component", function()
|
|
START(count(world:query(A, B, C, D)))
|
|
for _ in world:query(A, B, C, D) do end
|
|
end)
|
|
|
|
BENCH("8 component", function()
|
|
START(count(world:query(A, B, C, D, E, F, G, H)))
|
|
for _ in world:query(A, B, C, D, E, F, G, H) do end
|
|
end)
|
|
end
|
|
|
|
do TITLE "random components"
|
|
|
|
local world = jecs.World.new()
|
|
|
|
local A = world:component()
|
|
local B = world:component()
|
|
local C = world:component()
|
|
local D = world:component()
|
|
local E = world:component()
|
|
local F = world:component()
|
|
local G = world:component()
|
|
local H = world:component()
|
|
local I = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
if flip() then world:set(id, A, true) end
|
|
if flip() then world:set(id, B, true) end
|
|
if flip() then world:set(id, C, true) end
|
|
if flip() then world:set(id, D, true) end
|
|
if flip() then world:set(id, E, true) end
|
|
if flip() then world:set(id, F, true) end
|
|
if flip() then world:set(id, G, true) end
|
|
if flip() then world:set(id, H, true) end
|
|
if flip() then world:set(id, I, true) end
|
|
|
|
end
|
|
|
|
view_bench(world, A, B, C, D, E, F, G, H, I)
|
|
|
|
end
|
|
|
|
do TITLE "one component in common"
|
|
|
|
local world = jecs.World.new()
|
|
|
|
local A = world:component()
|
|
local B = world:component()
|
|
local C = world:component()
|
|
local D = world:component()
|
|
local E = world:component()
|
|
local F = world:component()
|
|
local G = world:component()
|
|
local H = world:component()
|
|
local I = world:component()
|
|
|
|
for i = 1, N do
|
|
local id = world:entity()
|
|
local a = true
|
|
if flip() then world:set(id, B, true) else a = false end
|
|
if flip() then world:set(id, C, true) else a = false end
|
|
if flip() then world:set(id, D, true) else a = false end
|
|
if flip() then world:set(id, E, true) else a = false end
|
|
if flip() then world:set(id, F, true) else a = false end
|
|
if flip() then world:set(id, G, true) else a = false end
|
|
if flip() then world:set(id, H, true) else a = false end
|
|
if flip() then world:set(id, I, true) else a = false end
|
|
if a then world:set(id, A, true) end
|
|
|
|
end
|
|
|
|
view_bench(world, A, B, C, D, E, F, G, H, I)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
do TITLE (testkit.color.white_underline("ECR query"))
|
|
|
|
local A = ecr.component()
|
|
local B = ecr.component()
|
|
local C = ecr.component()
|
|
local D = ecr.component()
|
|
local E = ecr.component()
|
|
local F = ecr.component()
|
|
local G = ecr.component()
|
|
local H = ecr.component()
|
|
local I = ecr.component()
|
|
|
|
local function count(query: () -> ())
|
|
local n = 0
|
|
for _ in query do
|
|
n += 1
|
|
end
|
|
return n
|
|
end
|
|
|
|
local function flip()
|
|
return math.random() > 0.5
|
|
end
|
|
|
|
local function view_bench(
|
|
world: ecr.Registry,
|
|
A: i53, B: i53, C: i53, D: i53, E: i53, F: i53, G: i53, H: i53, I: i53
|
|
)
|
|
|
|
BENCH("1 component", function()
|
|
START(count(world:view(A)))
|
|
for _ in world:view(A) do end
|
|
end)
|
|
|
|
BENCH("2 component", function()
|
|
START(count(world:view(A, B)))
|
|
for _ in world:view(A, B) do end
|
|
end)
|
|
|
|
BENCH("4 component", function()
|
|
START(count(world:view(A, B, C, D)))
|
|
for _ in world:view(A, B, C, D) do end
|
|
end)
|
|
|
|
BENCH("8 component", function()
|
|
START(count(world:view(A, B, C, D, E, F, G, H)))
|
|
for _ in world:view(A, B, C, D, E, F, G, H) do end
|
|
end)
|
|
end
|
|
|
|
|
|
do TITLE "random components"
|
|
local world = ecr.registry()
|
|
|
|
for i = 1, N do
|
|
local id = world.create()
|
|
if flip() then world:set(id, A, true) end
|
|
if flip() then world:set(id, B, true) end
|
|
if flip() then world:set(id, C, true) end
|
|
if flip() then world:set(id, D, true) end
|
|
if flip() then world:set(id, E, true) end
|
|
if flip() then world:set(id, F, true) end
|
|
if flip() then world:set(id, G, true) end
|
|
if flip() then world:set(id, H, true) end
|
|
if flip() then world:set(id, I, true) end
|
|
|
|
end
|
|
|
|
view_bench(world, A, B, C, D, E, F, G, H, I)
|
|
|
|
end
|
|
|
|
do TITLE "one component in common"
|
|
|
|
local world = ecr.registry()
|
|
|
|
for i = 1, N do
|
|
local id = world.create()
|
|
local a = true
|
|
if flip() then world:set(id, B, true) else a = false end
|
|
if flip() then world:set(id, C, true) else a = false end
|
|
if flip() then world:set(id, D, true) else a = false end
|
|
if flip() then world:set(id, E, true) else a = false end
|
|
if flip() then world:set(id, F, true) else a = false end
|
|
if flip() then world:set(id, G, true) else a = false end
|
|
if flip() then world:set(id, H, true) else a = false end
|
|
if flip() then world:set(id, I, true) else a = false end
|
|
if a then world:set(id, A, true) end
|
|
|
|
end
|
|
|
|
view_bench(world, A, B, C, D, E, F, G, H, I)
|
|
|
|
end
|
|
|
|
end |