mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-04 02:49:18 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			255 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Text
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Text
		
	
	
		
			Executable file
		
	
	
	
	
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
 | 
						|
 | 
						|
local N = 2 ^ 17
 | 
						|
 | 
						|
local pair = jecs.pair
 | 
						|
 | 
						|
do
 | 
						|
	TITLE("create")
 | 
						|
	local world = jecs.world()
 | 
						|
 | 
						|
	BENCH("entity", function()
 | 
						|
		for i = 1, START(N) do
 | 
						|
			world:entity()
 | 
						|
		end
 | 
						|
	end)
 | 
						|
 | 
						|
	local A = world:component()
 | 
						|
	local B = world:component()
 | 
						|
 | 
						|
	BENCH("pair", function()
 | 
						|
		for i = 1, START(N) do
 | 
						|
			jecs.pair(A, B)
 | 
						|
		end
 | 
						|
	end)
 | 
						|
end
 | 
						|
 | 
						|
do
 | 
						|
	TITLE("set")
 | 
						|
 | 
						|
	local world = jecs.world()
 | 
						|
	local A = world:component()
 | 
						|
 | 
						|
	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.
 | 
						|
do
 | 
						|
	TITLE("set relationship")
 | 
						|
 | 
						|
	local world = jecs.world()
 | 
						|
	local A = world:component()
 | 
						|
 | 
						|
	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
 | 
						|
 | 
						|
do
 | 
						|
	TITLE("get")
 | 
						|
 | 
						|
	local world = jecs.world()
 | 
						|
	local A = world:component()
 | 
						|
	local B = world:component()
 | 
						|
	local C = world:component()
 | 
						|
	local D = world:component()
 | 
						|
	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
 | 
						|
 | 
						|
do
 | 
						|
	TITLE("target")
 | 
						|
 | 
						|
	BENCH("1st target", function()
 | 
						|
		local world = jecs.world()
 | 
						|
		local A = world:component()
 | 
						|
		local B = world:component()
 | 
						|
		local C = world:component()
 | 
						|
		local D = world:component()
 | 
						|
		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))
 | 
						|
		end
 | 
						|
 | 
						|
		for i = 1, START(N) do
 | 
						|
			world:target(entities[i], A, 0)
 | 
						|
		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.
 | 
						|
do
 | 
						|
	TITLE(`query {N} entities`)
 | 
						|
 | 
						|
	local function view_bench(n: number)
 | 
						|
		BENCH(`{n} entities per archetype`, function()
 | 
						|
			local world = jecs.world()
 | 
						|
 | 
						|
			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)
 | 
						|
					world:add(id, ct)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			local q = world:query(A, B, C, D)
 | 
						|
			q:archetypes()
 | 
						|
			START()
 | 
						|
			for id in q do
 | 
						|
			end
 | 
						|
		end)
 | 
						|
 | 
						|
		BENCH(`inlined query`, function()
 | 
						|
			local world = jecs.world()
 | 
						|
			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)
 | 
						|
					world:add(id, ct)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			local archetypes = world:query(A, B, C, D):archetypes()
 | 
						|
			START()
 | 
						|
			-- for _, archetype in archetypes do
 | 
						|
			-- 	local columns, records = archetype.columns, archetype.records
 | 
						|
			-- 	local a = columns[records[A]]
 | 
						|
			-- 	local b = columns[records[B]]
 | 
						|
			-- 	local c = columns[records[C]]
 | 
						|
			-- 	local d = columns[records[D]]
 | 
						|
			-- 	for row in archetype.entities do
 | 
						|
			-- 		local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
 | 
						|
			-- 	end
 | 
						|
			-- end
 | 
						|
			for _, archetype in archetypes do
 | 
						|
				local columns_map = archetype.columns_map
 | 
						|
				local a = columns_map[A]
 | 
						|
				local b = columns_map[B]
 | 
						|
				local c = columns_map[C]
 | 
						|
				local d = columns_map[D]
 | 
						|
				for row in archetype.entities do
 | 
						|
					local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end)
 | 
						|
	end
 | 
						|
 | 
						|
	for i = 13, 0, -1 do
 | 
						|
		view_bench(2 ^ i)
 | 
						|
	end
 | 
						|
end
 |