5e0d58cfad
EN: 1.2.0.60 CN: 1.2.0.61 JP: 1.2.0.63 KR: 1.2.0.67
105 lines
3.1 KiB
Lua
105 lines
3.1 KiB
Lua
local get_time = os.clock
|
|
local sethook = xlua.sethook or debug.sethook
|
|
local func_info_map, start_time
|
|
local create_func_info = function(db_info)
|
|
return {
|
|
db_info = db_info,
|
|
count = 0,
|
|
total_time = 0
|
|
}
|
|
end
|
|
local on_hook = function(event, func_info_id, source)
|
|
if func_info_map == nil then
|
|
return
|
|
end
|
|
local func_info = func_info_map[func_info_id]
|
|
if not func_info then
|
|
func_info = create_func_info(debug.getinfo(2, "nS"))
|
|
func_info_map[func_info_id] = func_info
|
|
end
|
|
if event == "call" then
|
|
func_info.call_time = get_time()
|
|
func_info.count = func_info.count + 1
|
|
func_info.return_time = nil
|
|
elseif event == "return" or event == "tail return" then
|
|
local now = get_time()
|
|
if func_info.call_time then
|
|
func_info.total_time = func_info.total_time + (now - func_info.call_time)
|
|
func_info.call_time = nil
|
|
else
|
|
func_info.total_time = func_info.total_time + (now - (func_info.return_time or now))
|
|
func_info.count = func_info.count + 1
|
|
end
|
|
func_info.return_time = now
|
|
if source and func_info.count == 1 then
|
|
func_info.db_info.short_src = source
|
|
end
|
|
end
|
|
end
|
|
local start = function()
|
|
func_info_map = {}
|
|
start_time = get_time()
|
|
sethook(on_hook, "cr")
|
|
end
|
|
local pause = function()
|
|
sethook()
|
|
end
|
|
local resume = function()
|
|
sethook(on_hook, "cr")
|
|
end
|
|
local stop = function()
|
|
sethook()
|
|
func_info_map = nil
|
|
start_time = nil
|
|
end
|
|
local report_output_line = function(rp, stat_interval)
|
|
local source = rp.db_info.short_src or "[NA]"
|
|
local linedefined = rp.db_info.linedefined and rp.db_info.linedefined >= 0 and string.format(":%i", rp.db_info.linedefined) or ""
|
|
source = source .. linedefined
|
|
local name = rp.db_info.name or "[anonymous]"
|
|
local total_time = string.format("%04.3f", rp.total_time * 1000)
|
|
local average_time = string.format("%04.3f", rp.total_time / rp.count * 1000)
|
|
local relative_time = string.format("%03.2f%%", rp.total_time / stat_interval * 100)
|
|
local count = string.format("%7i", rp.count)
|
|
return string.format("|%-40.40s: %-50.50s: %-12s: %-12s: %-12s: %-12s|\n", name, source, total_time, average_time, relative_time, count)
|
|
end
|
|
local sort_funcs = {
|
|
TOTAL = function(a, b)
|
|
return a.total_time > b.total_time
|
|
end,
|
|
AVERAGE = function(a, b)
|
|
return a.average > b.average
|
|
end,
|
|
CALLED = function(a, b)
|
|
return a.count > b.count
|
|
end
|
|
}
|
|
local report = function(sort_by)
|
|
sethook()
|
|
local sort_func = type(sort_by) == "function" and sort_by or sort_funcs[sort_by]
|
|
local FORMAT_HEADER_LINE = "|%-40s: %-50s: %-12s: %-12s: %-12s: %-12s|\n"
|
|
local header = string.format(FORMAT_HEADER_LINE, "FUNCTION", "SOURCE", "TOTAL(MS)", "AVERAGE(MS)", "RELATIVE", "CALLED")
|
|
local stat_interval = get_time() - (start_time or get_time())
|
|
local report_list = {}
|
|
for _, rp in pairs(func_info_map or {}) do
|
|
table.insert(report_list, {
|
|
total_time = rp.total_time,
|
|
count = rp.count,
|
|
average = rp.total_time / rp.count,
|
|
output = report_output_line(rp, stat_interval)
|
|
})
|
|
end
|
|
table.sort(report_list, sort_func or sort_funcs.TOTAL)
|
|
local output = header
|
|
for i, rp in ipairs(report_list) do
|
|
output = output .. rp.output
|
|
end
|
|
sethook(on_hook, "cr")
|
|
return output
|
|
end
|
|
return {
|
|
start = start,
|
|
report = report,
|
|
stop = stop
|
|
}
|