-- In-depth execution speed benchmarker - read the /doc for more info
--
-- Always use rawget/rawset on _G to bypass strictlocal ActiveHooker = rawget(_G, "_BenchmarkerHooker")if ActiveHooker ~= nil then return ActiveHookerend
--
--local function dp(x, n) n = n or 4 return math.floor(x*10^n+0.5) / 10^nend
local function GetVarargInfo(...) return, select("#", ...)end
local function DetermineCaller(stacktrace) for line in stacktrace:gmatch("[^\n]+") do if not line:find("^stack traceback:") and not line:find("Aidan9382/Benchmarker") then local f, l = line:match("^%s*([^:]+):([^:]+)") return end endend
local CompleteCalls = local FunctionCallStack = local NoHookZone =
local function FinishUp -- Note: Don't currently use caller stats. Eh, whatever local TotalTimeTaken = 0 local ModuleTotalTimes = local FunctionTotalTimes = local SeenModules = local SeenFunctions = for _, Call in next, CompleteCalls do local CallTime = Call.TimeTaken - Call.Offset TotalTimeTaken = TotalTimeTaken + CallTime if not ModuleTotalTimes[Call.Origin] then ModuleTotalTimes[Call.Origin] = 0 SeenModules[#SeenModules+1] = Call.Origin end ModuleTotalTimes[Call.Origin] = ModuleTotalTimes[Call.Origin] + CallTime local UniqueName = Call.Origin .. "." .. Call.Name if not FunctionTotalTimes[UniqueName] then FunctionTotalTimes[UniqueName] = 0 SeenFunctions[#SeenFunctions+1] = UniqueName end FunctionTotalTimes[UniqueName] = FunctionTotalTimes[UniqueName] + CallTime end if TotalTimeTaken > .01 then table.sort(SeenModules, function(a, b) return ModuleTotalTimes[a] > ModuleTotalTimes[b] end) table.sort(SeenFunctions, function(a, b) return FunctionTotalTimes[a] > FunctionTotalTimes[b] end) mw.log("\n-- Benchmarker Finished --") mw.log("Total time taken: " .. dp(TotalTimeTaken)*1000 .. "ms") mw.log("\nTop 5 modules by time taken:") for i = 1, math.min(5, #SeenModules) do local t = dp(ModuleTotalTimes[SeenModules[i]]) mw.log(SeenModules[i] .. ": " .. t*1000 .. "ms (" .. dp(t/TotalTimeTaken, 3)*100 .. "%)") end mw.log("\nTop 5 functions by time taken:") for i = 1, math.min(5, #SeenFunctions) do local t = dp(FunctionTotalTimes[SeenFunctions[i]]) mw.log(SeenFunctions[i] .. ": " .. t*1000 .. "ms (" .. dp(t/TotalTimeTaken, 3)*100 .. "%)") end mw.log("") -- extra newline end CompleteCalls = end
local function HookFunction(f, fname, origin) if not NoHookZone[f] then local out = function(...) local callerinfo = DetermineCaller(debug.traceback) local StackObject = FunctionCallStack[#FunctionCallStack+1] = StackObject local s = os.clock local response, length = GetVarargInfo(f(...)) local timetaken = os.clock - s StackObject.TimeTaken = timetaken CompleteCalls[#CompleteCalls+1] = StackObject local maxi = #FunctionCallStack FunctionCallStack[maxi] = nil if maxi
"function" then return HookFunction(obj, "
--
--local require = requirelocal function hookedrequire(source) local out = require(source) if source ~= "strict" and source ~= "Module:Sandbox/Aidan9382/Benchmarker" then if type(out)
"function" then out = HookFunction(out, "
return HookTable