2024-09-17 00:40:31 +00:00
|
|
|
local jecs = require("@jecs")
|
|
|
|
local testkit = require("@testkit")
|
|
|
|
|
|
|
|
local BENCH, START = testkit.benchmark()
|
|
|
|
|
|
|
|
local function TITLE(s: string)
|
|
|
|
print()
|
|
|
|
print(testkit.color.white(s))
|
|
|
|
end
|
|
|
|
|
2024-10-12 20:18:11 +00:00
|
|
|
local N = 2 ^ 17
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local pair = jecs.pair
|
|
|
|
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE("create")
|
2024-09-17 00:40:31 +00:00
|
|
|
local world = jecs.World.new()
|
|
|
|
|
|
|
|
BENCH("entity", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:entity()
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2024-09-17 20:15:53 +00:00
|
|
|
local A = world:component()
|
2024-10-12 20:18:11 +00:00
|
|
|
local B = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
BENCH("pair", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
jecs.pair(A, B)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE("set")
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local world = jecs.World.new()
|
2025-03-09 21:45:41 +00:00
|
|
|
local A = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local entities = table.create(N)
|
|
|
|
|
|
|
|
for i = 1, N do
|
|
|
|
entities[i] = world:entity()
|
|
|
|
end
|
|
|
|
|
|
|
|
BENCH("add", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:set(entities[i], A, 1)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("set", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:set(entities[i], A, 2)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("remove", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:remove(entities[i], A)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- we have a separate benchmark for relationships.
|
|
|
|
-- this is due to that relationships have a very high id compared to normal
|
|
|
|
-- components, which cause them to get added into the hashmap portion.
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE("set relationship")
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local world = jecs.World.new()
|
2025-03-09 21:45:41 +00:00
|
|
|
local A = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local entities = table.create(N)
|
|
|
|
|
|
|
|
for i = 1, N do
|
|
|
|
entities[i] = world:entity()
|
|
|
|
world:set(entities[i], A, 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
local pair = jecs.pair(A, world:entity())
|
|
|
|
|
|
|
|
BENCH("add", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:set(entities[i], pair, 1)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("set", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:set(entities[i], pair, 2)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("remove", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:remove(entities[i], pair)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE("get")
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local world = jecs.World.new()
|
2024-09-17 20:15:53 +00:00
|
|
|
local A = world:component()
|
|
|
|
local B = world:component()
|
|
|
|
local C = world:component()
|
|
|
|
local D = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
local entities = table.create(N)
|
|
|
|
|
|
|
|
for i = 1, N do
|
|
|
|
entities[i] = world:entity()
|
|
|
|
world:set(entities[i], A, 1)
|
|
|
|
world:set(entities[i], B, 1)
|
|
|
|
world:set(entities[i], C, 1)
|
|
|
|
world:set(entities[i], D, 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
BENCH("1", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:get(entities[i], A)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("2", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:get(entities[i], A, B)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("3", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:get(entities[i], A, B, C)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
BENCH("4", function()
|
|
|
|
for i = 1, START(N) do
|
|
|
|
world:get(entities[i], A, B, C, D)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE("target")
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
BENCH("1st target", function()
|
|
|
|
local world = jecs.World.new()
|
2024-09-17 20:15:53 +00:00
|
|
|
local A = world:component()
|
|
|
|
local B = world:component()
|
|
|
|
local C = world:component()
|
|
|
|
local D = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
local entities = table.create(N)
|
|
|
|
|
|
|
|
for i = 1, N do
|
|
|
|
local ent = world:entity()
|
|
|
|
entities[i] = ent
|
|
|
|
|
|
|
|
world:set(ent, pair(A, A))
|
|
|
|
world:set(ent, pair(A, B))
|
|
|
|
world:set(ent, pair(A, C))
|
|
|
|
world:set(ent, pair(A, D))
|
2024-09-17 14:39:28 +00:00
|
|
|
end
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
for i = 1, START(N) do
|
2024-09-17 14:39:28 +00:00
|
|
|
world:target(entities[i], A, 0)
|
2024-09-17 00:40:31 +00:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
--- this benchmark is used to view how fragmentation affects query performance
|
|
|
|
--- we use this by determining how many entities should fit per arcehtype, instead
|
|
|
|
--- of creating x amount of archetypes. this would scale better with any amount of
|
|
|
|
--- entities.
|
2024-10-12 20:18:11 +00:00
|
|
|
do
|
|
|
|
TITLE(`query {N} entities`)
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
local function view_bench(n: number)
|
|
|
|
BENCH(`{n} entities per archetype`, function()
|
|
|
|
local world = jecs.World.new()
|
2024-09-17 20:15:53 +00:00
|
|
|
|
2024-09-17 14:39:28 +00:00
|
|
|
local A = world:component()
|
|
|
|
local B = world:component()
|
|
|
|
local C = world:component()
|
|
|
|
local D = world:component()
|
2024-09-17 00:40:31 +00:00
|
|
|
|
|
|
|
for i = 1, N, n do
|
|
|
|
local ct = world:entity()
|
|
|
|
for j = 1, n do
|
|
|
|
local id = world:entity()
|
|
|
|
world:set(id, A, true)
|
|
|
|
world:set(id, B, true)
|
|
|
|
world:set(id, C, true)
|
|
|
|
world:set(id, D, true)
|
2025-03-09 21:45:41 +00:00
|
|
|
world:add(id, ct)
|
2024-09-17 00:40:31 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-03-09 21:45:41 +00:00
|
|
|
local q = world:query(A, B, C, D)
|
2024-09-17 00:40:31 +00:00
|
|
|
START()
|
2025-03-09 21:45:41 +00:00
|
|
|
for id in q do
|
2024-09-17 00:40:31 +00:00
|
|
|
end
|
2024-09-17 14:39:28 +00:00
|
|
|
end)
|
2024-09-17 00:40:31 +00:00
|
|
|
|
2024-09-17 14:39:28 +00:00
|
|
|
BENCH(`inlined query`, function()
|
2024-10-12 20:18:11 +00:00
|
|
|
local world = jecs.World.new()
|
2024-09-17 14:39:28 +00:00
|
|
|
local A = world:component()
|
|
|
|
local B = world:component()
|
|
|
|
local C = world:component()
|
|
|
|
local D = world:component()
|
|
|
|
|
|
|
|
for i = 1, N, n do
|
|
|
|
local ct = world:entity()
|
|
|
|
for j = 1, n do
|
|
|
|
local id = world:entity()
|
|
|
|
world:set(id, A, true)
|
|
|
|
world:set(id, B, true)
|
|
|
|
world:set(id, C, true)
|
|
|
|
world:set(id, D, true)
|
2025-03-09 21:45:41 +00:00
|
|
|
world:add(id, ct)
|
2024-09-17 14:39:28 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-03-09 21:45:41 +00:00
|
|
|
local archetypes = world:query(A, B, C, D):archetypes()
|
2024-09-17 14:39:28 +00:00
|
|
|
START()
|
2025-03-09 21:45:41 +00:00
|
|
|
for _, archetype in archetypes do
|
2024-10-12 20:18:11 +00:00
|
|
|
local columns, records = archetype.columns, archetype.records
|
2025-03-09 21:45:41 +00:00
|
|
|
local a = columns[records[A]]
|
|
|
|
local b = columns[records[B]]
|
|
|
|
local c = columns[records[C]]
|
|
|
|
local d = columns[records[D]]
|
2024-10-12 20:18:11 +00:00
|
|
|
for row in archetype.entities do
|
2024-09-17 14:39:28 +00:00
|
|
|
local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
|
|
|
|
end
|
|
|
|
end
|
2024-09-17 00:40:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
for i = 13, 0, -1 do
|
2024-10-12 20:18:11 +00:00
|
|
|
view_bench(2 ^ i)
|
2024-09-17 14:39:28 +00:00
|
|
|
end
|
2024-09-17 00:40:31 +00:00
|
|
|
end
|