首先是开启监控器方法,向Global注入RawsetGlobal方法
function Profiler:StartMonitor(type)
self.MonitorType = type
self.MemoryState = {}
self.StartMemory = collectgarbage("count")
self.CurrentMemory = self.StartMemory
self.MonitorGlobal = {}
setmetatable(_G, { __newindex = Profiler.RawsetGlobal })
if type ~= self.MonitorType.Line or nil then
self.MonitorStartTime = os.clock()
self.FunctionTable = {}
debug.sethook(Profiler.FunctionMonitor,type.Type,0)
else
debug.sethook(Profiler.LineMonitor,type.Type,0)
end
end
function Profiler.RawsetGlobal(tb,k,v)
local t = {}
local info = debug.getinfo(2, "nlS")
t.CurrentLine = info.currentline
t.SrcFile = info.short_src
t.FunctionName = info.name or 'Anonymous'
t.Key = k
t.Value = v
Profiler.MonitorGlobal[k] = t
rawset(tb, k, v)
end
function性能监控方法,写法如出一辙
function Profiler.FunctionMonitor(type)
local funcinfo = debug.getinfo(2, 'ns')
if type == "call" then
Profiler:FunctionCall(funcinfo)
elseif type == "return" then
Profiler:FunctionReturn(funcinfo)
end
end
function Profiler:FunctionCall(funcinfo)
local functionTable = self:GetFunctionTable(funcinfo)
assert(functionTable)
if not functionTable.FunctionStartTime then
functionTable.FunctionStartTime = os.clock()
end
functionTable.CallTime = os.clock()
functionTable.CallCount = functionTable.CallCount + 1
end
function Profiler:FunctionReturn(funcinfo)
local stopTime = os.clock()
local report = self:FunctionReport(funcinfo)
assert(report)
report.StopTime = stopTime
if report.CallTime and report.CallTime > 0 then
report.TotalTime = report.TotalTime + (stopTime - report.CallTime)
end
report.localValueTable = report.localValueTable or {}
local index = 1
while true do
local key, value = debug.getlocal(2, index)
if not key then break end
rawset(report.localValueTable,key, value)
index = index + 1
end
end
function Profiler:GetFunctionTable(funcinfo)
local key = funcinfo.name or 'Unknow'
local report = self.PerformanceReport[key] or {}
if not report then
report ={CallCount = 0,TotalTime = 0}
self.FunctionTable[key] = report
end
return report
end
然后是结束监控返回self
function Profiler:StopMonitorFunction()
self.StopTime = os.clock()
self.SurplusMemory = self.CurrentMemory - self.StartMemory
debug.sethook()
local totalTime = self.StopTime - self.StartTime
table.sort(self.FunctionTable, function(a, b)
return a.Total_Time > b.Total_Time
end)
return self
end
附MonitorType
local m ={
__add = function(a,b)
local table = {}
table.Type = a.Type..b.Type
setmetatable(table,getmetatable(a))
return table
end,
__eq = function(a,b)
print(a.Type , b.Type)
return a.Type == b.Type
end
}
Profiler.MonitorTypeClass = {
New = function(value)
local table = {}
table.Type = value
setmetatable(table,m)
return table
end,
}
注:hook本身是会对原来的程序造成一定影响的,所以得出来的数据并非十分准确,最好是在另一个State开启注入