local s=game:GetService("\082\117\110\083\101\114\118\105\099\101")local Q=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local a=require(Q.Matter)local i=require(Q.Matter.immutable)local q=os.clock()local U=a.World.new()local z={}for s=1,300,1 do z[s]=a.component("\067\111\109\112\111\110\101\110\116 "..s)end local u={}for s=1,50,1 do local Q={}for s=1,math.random(2,30),1 do local a=math.random(1,#z)table.insert(Q,z[a])end u[s]=Q end for s=1,1000,1 do local Q={}local a=math.random(1,#u)for s,a in ipairs(u[a])do Q[a]=a({DummyData=math.random(1,5000)})end U:spawn(unpack(i.values(Q)))end local N=i.values(z)local b={}for s=1,200,1 do local Q=math.random(1,10)local a={}for s=1,Q,1 do table.insert(a,N[math.random(1,#N)])end table.insert(b,a)end local Y=os.clock()-q local c={}q=os.clock()s.Heartbeat:Connect(function()local s=0 local Q=os.clock()debug.profilebegin("\115\121\115\116\101\109\115")for Q,a in ipairs(b)do debug.profilebegin("\115\121\115\116\101\109")for Q,a in U:query(unpack(a))do U:insert(Q,a:patch({DummyData=a.DummyData+1}))s+=1 end U:optimizeQueries()debug.profileend()end debug.profileend()if os.clock()-q<4 then return end if c==nil then return elseif#c<1000 then table.insert(c,os.clock()-Q)else print("\097\100\100\101\100",s)print("\087\111\114\108\100 \099\114\101\097\116\101\100 \105\110",Y*1000,"\109\115")local Q=0 for s,a in ipairs(c)do Q+=a end print(("\065\118\101\114\097\103\101 \102\114\097\109\101 \116\105\109\101\058 \037\102\109\115"):format((Q/#c)*1000))c=nil local a=0 for s in pairs(U._entityArchetypeCache)do a+=1 end print(("\037\100 \101\110\116\105\116\105\101\115\n\037\100 \099\111\109\112\111\110\101\110\116\115\n\037\100 \115\121\115\116\101\109\115\n\037\100 \097\114\099\104\101\116\121\112\101\115"):format(U:size(),#z,#b,a))end end)
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Matter = require(ReplicatedStorage.Matter)
local immutable = require(ReplicatedStorage.Matter.immutable)

-- 500 entities
-- 2-30 components on each entity
-- 300 unique components
-- 200 systems
-- 1-10 components to query per system

local startTime = os.clock()

local world = Matter.World.new()

local components = {}

for i = 1, 300 do -- 300 components
	components[i] = Matter.component("Component " .. i)
end

local archetypes = {}
for i = 1, 50 do -- 50 archetypes
	local archetype = {}

	for _ = 1, math.random(2, 30) do
		local componentId = math.random(1, #components)

		table.insert(archetype, components[componentId])
	end

	archetypes[i] = archetype
end

for _ = 1, 1000 do -- 1000 entities in the world
	local componentsToAdd = {}

	local archetypeId = math.random(1, #archetypes)
	for _, component in ipairs(archetypes[archetypeId]) do
		componentsToAdd[component] = component({
			DummyData = math.random(1, 5000),
		})
	end

	world:spawn(unpack(immutable.values(componentsToAdd)))
end

local contiguousComponents = immutable.values(components)
local systemComponentsToQuery = {}

for _ = 1, 200 do -- 200 systems
	local numComponentsToQuery = math.random(1, 10)
	local componentsToQuery = {}

	for _ = 1, numComponentsToQuery do
		table.insert(componentsToQuery, contiguousComponents[math.random(1, #contiguousComponents)])
	end

	table.insert(systemComponentsToQuery, componentsToQuery)
end

local worldCreateTime = os.clock() - startTime
local results = {}
startTime = os.clock()

RunService.Heartbeat:Connect(function()
	local added = 0
	local systemStartTime = os.clock()
	debug.profilebegin("systems")
	for _, componentsToQuery in ipairs(systemComponentsToQuery) do
		debug.profilebegin("system")
		for entityId, firstComponent in world:query(unpack(componentsToQuery)) do
			world:insert(
				entityId,
				firstComponent:patch({
					DummyData = firstComponent.DummyData + 1,
				})
			)
			added += 1
		end
		world:optimizeQueries()
		debug.profileend()
	end
	debug.profileend()

	if os.clock() - startTime < 4 then
		-- discard first 4 seconds
		return
	end

	if results == nil then
		return
	elseif #results < 1000 then
		table.insert(results, os.clock() - systemStartTime)
	else
		print("added", added)
		print("World created in", worldCreateTime * 1000, "ms")
		local sum = 0
		for _, result in ipairs(results) do
			sum += result
		end
		print(("Average frame time: %fms"):format((sum / #results) * 1000))

		results = nil

		local n = 0

		for _ in pairs(world._entityArchetypeCache) do
			n += 1
		end

		print(
			("%d entities\n%d components\n%d systems\n%d archetypes"):format(
				world:size(),
				#components,
				#systemComponentsToQuery,
				n
			)
		)
	end
end)
