local function printf (fmt,...) log (string.format(fmt,...)) end local Counters = {} local Names = {} local timer = profile_timer() local old_hook_func, old_hook_mask, old_hook_count local started = false local function getname (func) local n = Names[func] local loc = string.format("[%s]:%s", n.short_src, n.linedefined) if "" ~= n.namewhat then return (string.format("%s (%s)", loc, n.name)) else return (string.format("%s", loc)) end end local function hook (context,line_number) -- if nil ~= old_hook_func then -- if old_hook_func ~= hook then -- old_hook_func (context,line_number) -- end -- end assert ("line" ~= context) local f = debug.getinfo(2, "f").func local caller = debug.getinfo(3, "f") local g = nil if caller ~= nil then g = caller.func; end --[[ local f_name = nil local g_name = nil local old_g = Names[g] if (Names[f] == nil) then Names[f] = debug.getinfo(2,"Sn") f_name = getname(f) Names[f] = nil else f_name = getname(f) end if (g == nil) then g_name = "" else if (Names[g] == nil) then Names[g] = debug.getinfo(3,"Sn") g_name = "from [" .. getname(g) .. "]" Names[g] = nil else g_name = "from [" .. getname(g) .. "]" end end printf ("%6s : [%s]%s",context,f_name,g_name) ]] if ("return" == context) then local object = Counters[f] if (object ~= nil) then object.timer:stop () object.child_timer:stop () if (g ~= nil) then local object = Counters[g] if (object ~= nil) then object.timer:start () end end end return end if ("tail return" == context) then if (g ~= nil) then local object = Counters[g] if (object ~= nil) then object.timer:start () end end return end assert ("call" == context) if g ~= nil then local object = Counters[g] if (object ~= nil) then object.timer:stop () end end if (Counters[f] == nil) then Counters[f] = {count=1,timer=profile_timer(),child_timer=profile_timer()} local object = Counters[f] object.child_timer:start () object.timer:start () Names[f] = debug.getinfo(2,"Sn") else local object = Counters[f] object.count = object.count + 1 object.child_timer:start () object.timer:start () end end function setup_hook (do_not_print_message) if started == true then return end timer:start () old_hook_func, old_hook_mask, old_hook_count = debug.gethook(); debug.sethook () debug.sethook (hook, "cr") started = true if (do_not_print_message ~= true) then printf ("profiler is activated") end end function clear_hook () if started == false then printf ("profiler hook wasn't setup!") return; end -- debug.sethook (old_hook_func,old_hook_mask,old_hook_count) debug.sethook () timer:stop () started = false end function stats () if started == false then printf ("profiler hook wasn't setup!") return end clear_hook () printf ("profiler statistics") local sort_stats = {} for func, count in pairs(Counters) do local n = getname(func) if (nil == sort_stats[n]) then sort_stats[n] = count else sort_stats[n].count = sort_stats[n].count + count.count sort_stats[n].timer = sort_stats[n].timer + count.timer sort_stats[n].child_timer = sort_stats[n].child_timer + count.child_timer end end local script = profile_timer() local count = 0 local out_stats = {} for i,j in pairs(sort_stats) do local k = i if k == "[[C]]:-1" then k = "#uncrecognized C/C++ stuff" end table.insert (out_stats,{name=k,count=j}) script = script + j.timer count = count + j.count end table.sort ( out_stats, function (a,b) return (a.count.timer < b.count.timer) end ) printf ("total_time (pecent) child_time [total_call_count][average_call_time]") for n,c in pairs(out_stats) do printf ("%9.2fms (%5.2f%%) %9.2fms [%8d][%9.2fmks] : %s",c.count.timer:time()/1000,c.count.timer:time()*100/script:time(),c.count.child_timer:time()/1000,c.count.count, c.count.timer:time()/(c.count.count),c.name) end printf ("") printf (" pure time : %%%% : children : count : function name") printf ("") printf ("profile time : %8.2fms",timer:time()/1000) printf ("script time : %8.2fms (%5.2f%%)",script:time()/1000,script:time()*100/timer:time()) printf ("call count : %8d",count) setup_hook (true) end function clear () if started == true then clear_hook () end Counters = {} Names = {} timer = profile_timer() setup_hook (true) end