模組:沙盒/Justin545/Timeit

-- Source: https://ja.wikipedia.org/w/index.php?title=%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB:%E3%82%B5%E3%83%B3%E3%83%89%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9/Ef3/Timeit&oldid=94418284

require('strict')

local p = {
	timeitFunction = function(f, ...)
		local t = os.clock()
		local r = f(...) -- use xpcall()???
		return os.clock() - t, r
	end,
	timeitMethod = function(this, m, ...)
		local t = os.clock()
		local r = m(this,...) -- use xpcall()???
		return os.clock() - t, r
	end,
	timeitTemplate = function(frame)
		local args = frame.args
		if not true then return mw.dumpObject(frame) end
		local t = os.clock()
		local r = frame:expandTemplate{ title = args.tmpl, args = args }
		return r .." --- ".. (os.clock() - t) .. "(second)"
	end
}
	p.traverse = function(obj,name,level)
		level = level or 3
		if level < 0 then return nil end
		name = name or "ROOT"
		local result = {}
		if type(obj) == "function" then
			result = "function"
		elseif type(obj) == "table" then
			for k,v in pairs(obj) do 
				if type(v) == "function" then
					result[#result + 1] = ("%s.%s()"):format(name,k)
				elseif type(v) == "table" then
					result[#result + 1] = p.traverse(v, ("%s.%s"):format(name,k), level - 1)
				end
			end
		end
		return result
	end

p.GlobalFunctionTable=nil
p.RGlobalFunctionTable=nil
p.getGlobalFunctionTable = function()
	if p.GlobalFunctionTable then
		return p.GlobalFunctionTable
	end
	p.GlobalFunctionTable = {}
	p.RGlobalFunctionTable = {}

	for k, v in pairs(package.loaded) do
		if type(v) == "table" then
			local nn = k == "_G" and "" or (k .. ".")
			for kk, vv in pairs(v) do
				if type(vv) == "function" then
					p.GlobalFunctionTable[nn..kk] = vv
					p.RGlobalFunctionTable[vv] = p.RGlobalFunctionTable[vv] or {}
					p.RGlobalFunctionTable[vv][#p.RGlobalFunctionTable[vv] + 1] = nn..kk
				end
			end
		end
	end
	return p.GlobalFunctionTable
end

p.sethook = function()
	p.total, p.calls = {}, {}
	p.unpack = unpack
	p.osclock = os.clock
	p.airs = pairs
	p.type = type
	for k, v in p.airs(package.loaded) do
		if p.type(v) == "table" then
			local nn = k == "_G" and "" or (k .. ".")
			for kk, vv in p.airs(v) do
				if p.type(vv) == "function" then
					v[kk] = function(...)
						local t = p.osclock()
						local result = {vv(...)}
						p.total[kk] = (p.total[kk] or 0) + (p.osclock() - t)
						p.calls[kk] = (p.calls[kk] or 0) + 1
						return p.unpack(result)
					end
				end
			end
		end
	end
	return p
end

p.status = function()
	local result = ""
	for k, v in pairs(p.total) do
		result = result .. ("%s:\t%f / %d = %f\n"):format(k,v,p.calls[k],v/p.calls[k])
	end
	return result
end

p.prof = function(f, ...)
	p.sethook()
	local r = f(...) -- use xpcall()???
	return p.status(), r
end
	
return p