miduo_client/Assets/ManagedResources/~Lua/UnityEngine/Profiler.lua

282 lines
7.4 KiB
Lua

--------------------------------------------------------------------------------
-- Copyright (c) 2015 - 2018 , 蒙占志(topameng) topameng@gmail.com
-- All rights reserved.
-- Use, modification and distribution are subject to the "MIT License"
--------------------------------------------------------------------------------
local LuaProfiler = LuaProfiler
local vmdef = jit and require("jit.vmdef")
--通过文件名和行数指定一个函数名字
local ffnames =
{
event =
{
[20] = "_xpcall.__call",
[142] = "event.__call",
},
slot =
{
[11] = "slot.__call",
},
MainScene =
{
[250] = "MainScene.Update"
}
}
--不需要Profiler的函数
local blacklist =
{
["ipairs_aux"] = 1,
["_xpcall.__call"] = 1,
["unknow"] = 1,
}
local profiler =
{
mark = 1,
cache = 1,
}
local stacktrace = {}
function profiler:scan(t, name)
if self.mark[t] then
return
end
self.mark[t] = true
for k, v in pairs(t) do
if type(k) == "string" then
if type(v) == "function" then
local str = k
if name then
str = name ..".".. str
end
if not blacklist[str] and k ~= "__index" and k ~= "__newindex" then
self.cache[v] = {name = str, id = -1}
end
elseif type(v) == "table" and not self.mark[v] then
self:scan(v, k)
end
elseif name and k == tolua.gettag or k == tolua.settag then
self:scan(v, name)
end
end
end
function profiler:scanlibs()
local t = package.loaded
self.mark[t] = true
for k, v in pairs(t) do
if type(k) == "string" and type(v) == "table" then
self:scan(v, k)
local mt = getmetatable(v)
if mt then
self:scan(mt, k)
end
end
end
end
local function findstack(func)
local pos = #stacktrace + 1
for i, v in ipairs(stacktrace) do
if v == func then
pos = i
end
end
return pos
end
local function jitreturn(count)
local top = #stacktrace
if top > 0 then
local ar = debug.getinfo (5, "f")
if ar then
local func = ar.func
local index = findstack(func)
if index > top then
ar = debug.getinfo(6, "f")
if ar then
func = ar.func
index = findstack(func) or index
end
end
for i = index + 1, top do
table.remove(stacktrace)
LuaProfiler.EndSample()
end
end
end
end
local function BeginSample(name, func, cache)
jitreturn()
table.insert(stacktrace, func)
if cache.id == -1 then
cache.name = name
cache.id = LuaProfiler.GetID(name)
end
LuaProfiler.BeginSample(cache.id)
end
local function BeginSampleNick(name, func, cache)
jitreturn()
table.insert(stacktrace, func)
local id = -1
if cache.nick == nil then
cache.nick = {}
end
id = cache.nick[name]
if not id then
id = LuaProfiler.GetID(name)
cache.nick[name] = id
end
LuaProfiler.BeginSample(id)
end
function profiler_hook(event, line)
if event == 'call' then
local name = nil
local func = debug.getinfo (2, 'f').func
local cache = profiler.cache[func]
if cache then
name = cache.name
end
if blacklist[name] then
return
end
if name == "event.__call" then
local ar = debug.getinfo (2, 'n')
BeginSampleNick(ar.name or name, func, cache)
elseif name then
BeginSample(name, func, cache)
else
local ar = debug.getinfo (2, 'Sn')
local method = ar.name
local linedefined = ar.linedefined
if not cache then
cache = {name = "unknow", id = -1}
profiler.cache[func] = cache
end
if ar.short_src == "[C]" then
if method == "__index" or method == "__newindex" then
return
end
local name = tostring(func)
local index = name:match("function: builtin#(%d+)")
if not index then
if method then
name = method
BeginSample(method, func, cache)
elseif linedefined ~= -1 then
name = ar.short_src .. linedefined
BeginSample(name, func, cache)
end
else
name = vmdef.ffnames[tonumber(index)]
if not blacklist[name] then
BeginSample(name, func, cache)
end
end
elseif linedefined ~= -1 or method then
local short_src = ar.short_src
method = method or linedefined
local name = nil
name = short_src:match('([^/\\]+)%.%w+$')
name = name or short_src:match('([^/\\]+)$')
local ffname = ffnames[name]
if ffname then
name = ffname[linedefined]
else
name = name .. "." .. method
end
if not name then
name = short_src .. "." .. method
end
BeginSample(name, func, cache)
else
BeginSample(name, func, cache)
end
end
elseif event == "return" then
local top = #stacktrace
if top == 0 then
return
end
local ar = debug.getinfo (2, 'f')
if ar.func == stacktrace[top] then
table.remove(stacktrace)
LuaProfiler.EndSample()
else
local index = findstack(ar.func)
if index > top then return end
for i = index, top do
table.remove(stacktrace)
LuaProfiler.EndSample()
end
end
end
end
function profiler:start()
self.mark = {}
self.cache = {__mode = "k"}
self:scan(_G, nil)
self:scanlibs()
self.mark = nil
debug.sethook(profiler_hook, 'cr', 0)
end
function profiler:print()
for k, v in pairs(self.cache) do
print(v.name)
end
end
function profiler:stop()
debug.sethook(nil)
self.cache = nil
end
return profiler