|
|
- LuaProfiler = {}
- LuaProfiler.is_playing = false
-
- function LuaProfiler.SwitchState()
- LuaProfiler.is_playing = not LuaProfiler.is_playing
- if LuaProfiler.is_playing then
- LuaProfiler.start()
- else
- LuaProfiler.stop()
- end
- end
-
- -- get the function title
- function LuaProfiler._func_title(funcinfo)
-
- -- check
- assert(funcinfo)
-
- -- the function name
- local name = funcinfo.name or 'none_name'
-
- -- the function line
- -- print("_func_title = ", name)
- local line = string.format("%d", funcinfo.linedefined or 0)
-
- -- the function source
- local source = funcinfo.short_src or 'C_FUNC'
- -- if os.isfile(source) then
- -- source = path.relative(source, xmake._PROGRAM_DIR)
- -- end
-
- -- make title
- return string.format("%-30s: %s: %s", name, source, line), source
- end
-
- -- get the function report
- function LuaProfiler._func_report(funcinfo)
-
- -- get the function title
- local title, source = LuaProfiler._func_title(funcinfo)
-
- -- get the function report
- local report = LuaProfiler._REPORTS_BY_TITLE[title]
- if not report then
-
- -- init report
- report =
- {
- title = LuaProfiler._func_title(funcinfo)
- , source = source
- , callcount = 0
- , totaltime = 0
- }
-
- -- save it
- LuaProfiler._REPORTS_BY_TITLE[title] = report
- table.insert(LuaProfiler._REPORTS, report)
- end
-
- -- ok?
- return report
- end
-
- -- profiling call
- function LuaProfiler._profiling_call(funcinfo)
-
- -- get the function report
- local report = LuaProfiler._func_report(funcinfo)
- assert(report)
-
- -- save the call time
- report.calltime = os.clock()
-
- -- update the call count
- report.callcount = report.callcount + 1
-
- end
-
- -- profiling return
- function LuaProfiler._profiling_return(funcinfo)
-
- -- get the stoptime
- local stoptime = os.clock()
-
- -- get the function report
- local report = LuaProfiler._func_report(funcinfo)
- assert(report)
-
- -- update the total time
- if report.calltime and report.calltime > 0 then
- report.totaltime = report.totaltime + (stoptime - report.calltime)
- report.calltime = 0
- end
- end
-
- -- the profiling handler
- function LuaProfiler._profiling_handler(hooktype)
-
- -- the function info
- local funcinfo = debug.getinfo(2, 'nS')
- -- print("_profiling_handler = ", hooktype)
- -- dispatch it
- if hooktype == "call" then
- LuaProfiler._profiling_call(funcinfo)
- elseif hooktype == "return" then
- LuaProfiler._profiling_return(funcinfo)
- end
- end
-
- -- the tracing handler
- function LuaProfiler._tracing_handler(hooktype)
-
- -- the function info
- local funcinfo = debug.getinfo(2, 'nS')
-
- -- is call?
- if hooktype == "call" then
-
- -- is xmake function?
- local name = funcinfo.name
- local source = funcinfo.short_src or 'C_FUNC'
- if name then-- and os.isfile(source) then
-
- -- the function line
- local line = string.format("%d", funcinfo.linedefined or 0)
-
- -- get the relative source
- -- source = path.relative(source, xmake._PROGRAM_DIR)
-
- -- trace it
- print(string.format("%-30s: %s: %s", name, source, line))
- end
- end
- end
-
- -- start profiling
- function LuaProfiler.start(mode)
-
- -- trace?
- if mode and mode == "trace" then
- debug.sethook(LuaProfiler._tracing_handler, 'cr', 0)
- else
- -- init reports
- LuaProfiler._REPORTS = {}
- LuaProfiler._REPORTS_BY_TITLE = {}
- LuaProfiler._CUSTOM_REPORTS = ""
- print("----------------------------------------------->>LuaProfiler.start")
-
- -- save the start time
- LuaProfiler._STARTIME = os.clock()
-
- -- start to hook
- debug.sethook(LuaProfiler._profiling_handler, 'cr', 0)
- end
- end
-
- -- stop profiling
- function LuaProfiler.stop(mode)
-
- -- trace?
- if mode and mode == "trace" then
-
- -- stop to hook
- debug.sethook()
-
- else
- print("----------------------------------------------->>LuaProfiler.stop")
- -- save the stop time
- LuaProfiler._STOPTIME = os.clock()
-
- -- stop to hook
- debug.sethook()
-
- -- calculate the total time
- local totaltime = LuaProfiler._STOPTIME - LuaProfiler._STARTIME
- print("totaltime = " , totaltime)
-
- -- sort reports
- table.sort(LuaProfiler._REPORTS, function(a, b)
- return a.totaltime > b.totaltime
- end)
-
- -- show reports
- local total_percent = 0
- local class_list = {}
- for _, report in ipairs(LuaProfiler._REPORTS) do
-
- -- calculate percent
- local percent = (report.totaltime / totaltime) * 100
- total_percent = total_percent + percent
- if percent < 0.1 then
- break
- end
- local vo = class_list[report.source]
- if vo == nil then
- vo = {}
- class_list[report.source] = vo
- vo.totaltime = 0
- vo.percent = 0
- vo.callcount = 0
- end
-
- vo.totaltime = vo.totaltime + report.totaltime
- vo.percent = vo.percent + percent
- vo.callcount = vo.callcount + report.callcount
- -- trace
- local temp_str = string.format("totaltime = %6.3f, percent = %6.2f%%, count =%7d, pos = %s", report.totaltime, percent, report.callcount, report.title)
- -- print(temp_str)
- LuaProfiler._CUSTOM_REPORTS = LuaProfiler._CUSTOM_REPORTS .. temp_str .."\n"
- end
-
- print("----------------------------------------------->>class_list")
- local new_list = {}
- for k,v in pairs(class_list) do
- v.source = k
- table.insert(new_list, v)
- end
- table.sort(new_list, function(a, b)
- return a.totaltime > b.totaltime
- end)
-
- for source, info in ipairs(new_list) do
- local temp_str = string.format("totaltime = %6.3f, percent = %6.2f%%, count =%7d, pos = %s", info.totaltime, info.percent, info.callcount, info.source)
- -- print(temp_str)
- LuaProfiler._CUSTOM_REPORTS = LuaProfiler._CUSTOM_REPORTS .. temp_str .."\n"
- end
- end
- end
|