localfunctioncc(i) if i <= 0then return0 end cc(i-1) end
localfunctionaa() local j = 0 for i=1, 100do cc(10) end end
local lst_item = {} local map_record = {} debug.sethook(function(hook_type) local func_info = debug.getinfo(2, 'nSl') local key = func_info.short_src ..":".. func_info.linedefined
local now = os.clock() if hook_type == "call"then table.insert(lst_item,{ call_time = now, key = key, }) elseif hook_type == "return"then local item = table.remove(lst_item) ifnot item thenreturnend
local record = map_record[key] if record then record.call_count = record.call_count + 1 record.total_time = record.total_time + (now - item.call_time) else map_record[key] = { call_count = 1, total_time = now - item.call_time, name = func_info.name, line = func_info.linedefined, source = func_info.short_src, } end end end, 'cr', 0)
local start_time = os.clock() aa()
local total_time = 0 for k,v inpairs(map_record) do total_time = total_time + v.total_time local use_time = string.format("%4.3f", v.total_time) print(string.format("%7s %10d %20s %s", use_time, v.call_count, v.name, k)) end print("-----------------------") print("total_time: ", total_time) print("real use time:", os.clock() - start_time)
output:
1 2 3 4 5
0.0161 aa test.lua:8 0.0621100 cc test.lua:1 ----------------------- total_time: 0.078125 real use time: 0.015625
local lst_item = {} local map_record = {} debug.sethook(function(hook_type) local func_info = debug.getinfo(2, 'nSl') local key = func_info.short_src ..":".. func_info.linedefined
local now = gettime() if hook_type == "call"then table.insert(lst_item,{ call_time = now, key = key, sub_cost = 0, name = func_info.name, }) elseif hook_type == "return"then local item = table.remove(lst_item) ifnot item thenreturnend
local record = map_record[key] if record then record.call_count = record.call_count + 1 record.total_time = record.total_time + (now - item.call_time - item.sub_cost) else map_record[key] = { call_count = 1, total_time = now - item.call_time - item.sub_cost, name = item.name, line = func_info.linedefined, source = func_info.short_src, } end if #lst_item > 0then lst_item[#lst_item].sub_cost = lst_item[#lst_item].sub_cost + (now - item.call_time) end end end, 'cr', 0)
output:
1 2 3 4 5
0.00016551 aa test.lua:12 0.00349161100 cc test.lua:5 ----------------------- total_time: 0.0039355754852295 real use time: 0.0062041282653809
尾递归问题
下面把cc函数改成尾递归,执行结果如下:
1 2 3 4 5 6
0.00000795 gettime [C]:-1 0.0018032100 cc test.lua:5 0.00023871 aa test.lua:12 ----------------------- total_time: 0.0020496845245361 real use time: 0.0020508766174316
local lst_item = {} local map_record = {} debug.sethook(function(hook_type) local func_info = debug.getinfo(2, 'nSl') local key = func_info.short_src ..":".. func_info.linedefined
local now = gettime() if hook_type == "call"or hook_type == 'tail call'then table.insert(lst_item,{ call_time = now, key = key, sub_cost = 0, name = func_info.name, is_tail = hook_type == 'tail call', }) elseif hook_type == "return"then local is_tail = true while is_tail and #lst_item > 0do local item = table.remove(lst_item)
is_tail = item.is_tail local record = map_record[key] if record then record.call_count = record.call_count + 1 record.total_time = record.total_time + (now - item.call_time - item.sub_cost) else map_record[key] = { call_count = 1, total_time = now - item.call_time - item.sub_cost, name = item.name, line = func_info.linedefined, source = func_info.short_src, } end if #lst_item > 0then lst_item[#lst_item].sub_cost = lst_item[#lst_item].sub_cost + (now - item.call_time) end end end end, 'cr', 0)
output:
1 2 3 4 5 6
0.00187441100nil test.lua:5 0.00044561 aa test.lua:12 0.001046415 gettime [C]:-1 ----------------------- total_time: 0.0033664703369141 real use time: 0.0023291110992432