local function Y(j,D)for j,E in ipairs(j:GetChildren())do if E:IsA("\077\111\100\117\108\101\083\099\114\105\112\116")and E.Name:match("\037\046\098\101\110\099\104\036")then table.insert(D,E)end Y(E,D)end end local function j() end local D={}local function E(Y)if D[Y]~=nil then return D[Y]end local E=tick()for Y=1,Y,1 do j()end local T=tick()local K=T-E D[Y]=K return K end local T={}Y(script,T)table.sort(T,function(Y,j)return Y.Name<j.Name end)local K=("\083\116\097\114\116\105\110\103 \037\100 \098\101\110\099\104\109\097\114\107\115\046\046\046"):format(#T)print(K)print()for Y,j in ipairs(T)do local D=require(j)if D.setup~=nil then D.setup()end local T=tick()local K=D.step for Y=1,D.iterations,1 do K(Y)end local B=tick()if D.teardown~=nil then D.teardown()end local x=(B-T)-E(D.iterations)local R=("\066\101\110\099\104\109\097\114\107 \037\115\058\n\t\040\037\100 \105\116\101\114\097\116\105\111\110\115\041 \116\111\111\107 \037\102 \115 \040\037\102 \110\115\047\105\116\101\114\097\116\105\111\110\041"):format(j.Name,D.iterations,x,(1000000000.0*x)/D.iterations)print(R)print()end print("\066\101\110\099\104\109\097\114\107\115 \099\111\109\112\108\101\116\101\033")
--[[
	Locate all .bench.lua files in the given Roblox tree.
]]
local function findBenchmarkModules(root, moduleList)
	for _, child in ipairs(root:GetChildren()) do
		if child:IsA("ModuleScript") and child.Name:match("%.bench$") then
			table.insert(moduleList, child)
		end

		findBenchmarkModules(child, moduleList)
	end
end

local function noop() end

local emptyTimes = {}
local function getEmptyTime(iterations)
	if emptyTimes[iterations] ~= nil then
		return emptyTimes[iterations]
	end

	local startTime = tick()

	for _ = 1, iterations do
		noop()
	end

	local endTime = tick()

	local result = endTime - startTime
	emptyTimes[iterations] = result

	return result
end

local benchmarkModules = {}

findBenchmarkModules(script, benchmarkModules)

table.sort(benchmarkModules, function(a, b)
	return a.Name < b.Name
end)

local startMessage = ("Starting %d benchmarks..."):format(#benchmarkModules)
print(startMessage)
print()

for _, module in ipairs(benchmarkModules) do
	local benchmark = require(module)

	if benchmark.setup ~= nil then
		benchmark.setup()
	end
	local startTime = tick()
	local step = benchmark.step

	for i = 1, benchmark.iterations do
		step(i)
	end

	local endTime = tick()
	if benchmark.teardown ~= nil then
		benchmark.teardown()
	end

	local totalTime = (endTime - startTime) - getEmptyTime(benchmark.iterations)

	local message = ("Benchmark %s:\n\t(%d iterations) took %f s (%f ns/iteration)"):format(
		module.Name,
		benchmark.iterations,
		totalTime,
		1e9 * totalTime / benchmark.iterations
	)

	print(message)
	print()
end

print("Benchmarks complete!")
