Compare commits
No commits in common. '451d7103261d26c77f6cb5f513e81dcf47333c84' and '7da12d303545d940cfdb5a4b78bab599292f201b' have entirely different histories.
451d710326
...
7da12d3035
@ -1,8 +1,7 @@ |
|||||||
--Config file for the game |
--Config file for the game |
||||||
function love.conf(t) |
function love.conf(t) |
||||||
t.window.width = 1366 |
t.window.width = 1600 |
||||||
t.window.height = 768 |
t.window.height = 960 |
||||||
t.window.title = "Tanks-A-Lot" |
t.window.title = "Tanks-A-Lot" |
||||||
t.window.resizable = true |
|
||||||
t.version = "11.5" |
t.version = "11.5" |
||||||
end |
end |
||||||
|
@ -0,0 +1,195 @@ |
|||||||
|
local clock = os.clock |
||||||
|
|
||||||
|
--- Simple profiler written in Lua. |
||||||
|
-- @module profile |
||||||
|
-- @alias profile |
||||||
|
local profile = {} |
||||||
|
|
||||||
|
-- function labels |
||||||
|
local _labeled = {} |
||||||
|
-- function definitions |
||||||
|
local _defined = {} |
||||||
|
-- time of last call |
||||||
|
local _tcalled = {} |
||||||
|
-- total execution time |
||||||
|
local _telapsed = {} |
||||||
|
-- number of calls |
||||||
|
local _ncalls = {} |
||||||
|
-- list of internal profiler functions |
||||||
|
local _internal = {} |
||||||
|
|
||||||
|
--- This is an internal function. |
||||||
|
-- @tparam string event Event type |
||||||
|
-- @tparam number line Line number |
||||||
|
-- @tparam[opt] table info Debug info table |
||||||
|
function profile.hooker(event, line, info) |
||||||
|
info = info or debug.getinfo(2, "fnS") |
||||||
|
local f = info.func |
||||||
|
-- ignore the profiler itself |
||||||
|
if _internal[f] or info.what ~= "Lua" then |
||||||
|
return |
||||||
|
end |
||||||
|
-- get the function name if available |
||||||
|
if info.name then |
||||||
|
_labeled[f] = info.name |
||||||
|
end |
||||||
|
-- find the line definition |
||||||
|
if not _defined[f] then |
||||||
|
_defined[f] = info.short_src .. ":" .. info.linedefined |
||||||
|
_ncalls[f] = 0 |
||||||
|
_telapsed[f] = 0 |
||||||
|
end |
||||||
|
if _tcalled[f] then |
||||||
|
local dt = clock() - _tcalled[f] |
||||||
|
_telapsed[f] = _telapsed[f] + dt |
||||||
|
_tcalled[f] = nil |
||||||
|
end |
||||||
|
if event == "tail call" then |
||||||
|
local prev = debug.getinfo(3, "fnS") |
||||||
|
profile.hooker("return", line, prev) |
||||||
|
profile.hooker("call", line, info) |
||||||
|
elseif event == "call" then |
||||||
|
_tcalled[f] = clock() |
||||||
|
else |
||||||
|
_ncalls[f] = _ncalls[f] + 1 |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
--- Sets a clock function to be used by the profiler. |
||||||
|
-- @tparam function func Clock function that returns a number |
||||||
|
function profile.setclock(f) |
||||||
|
assert(type(f) == "function", "clock must be a function") |
||||||
|
clock = f |
||||||
|
end |
||||||
|
|
||||||
|
--- Starts collecting data. |
||||||
|
function profile.start() |
||||||
|
if rawget(_G, "jit") then |
||||||
|
jit.off() |
||||||
|
jit.flush() |
||||||
|
end |
||||||
|
debug.sethook(profile.hooker, "cr") |
||||||
|
end |
||||||
|
|
||||||
|
--- Stops collecting data. |
||||||
|
function profile.stop() |
||||||
|
debug.sethook() |
||||||
|
for f in pairs(_tcalled) do |
||||||
|
local dt = clock() - _tcalled[f] |
||||||
|
_telapsed[f] = _telapsed[f] + dt |
||||||
|
_tcalled[f] = nil |
||||||
|
end |
||||||
|
-- merge closures |
||||||
|
local lookup = {} |
||||||
|
for f, d in pairs(_defined) do |
||||||
|
local id = (_labeled[f] or "?") .. d |
||||||
|
local f2 = lookup[id] |
||||||
|
if f2 then |
||||||
|
_ncalls[f2] = _ncalls[f2] + (_ncalls[f] or 0) |
||||||
|
_telapsed[f2] = _telapsed[f2] + (_telapsed[f] or 0) |
||||||
|
_defined[f], _labeled[f] = nil, nil |
||||||
|
_ncalls[f], _telapsed[f] = nil, nil |
||||||
|
else |
||||||
|
lookup[id] = f |
||||||
|
end |
||||||
|
end |
||||||
|
collectgarbage("collect") |
||||||
|
end |
||||||
|
|
||||||
|
--- Resets all collected data. |
||||||
|
function profile.reset() |
||||||
|
for f in pairs(_ncalls) do |
||||||
|
_ncalls[f] = 0 |
||||||
|
end |
||||||
|
for f in pairs(_telapsed) do |
||||||
|
_telapsed[f] = 0 |
||||||
|
end |
||||||
|
for f in pairs(_tcalled) do |
||||||
|
_tcalled[f] = nil |
||||||
|
end |
||||||
|
collectgarbage("collect") |
||||||
|
end |
||||||
|
|
||||||
|
--- This is an internal function. |
||||||
|
-- @tparam function a First function |
||||||
|
-- @tparam function b Second function |
||||||
|
-- @treturn boolean True if "a" should rank higher than "b" |
||||||
|
function profile.comp(a, b) |
||||||
|
local dt = _telapsed[b] - _telapsed[a] |
||||||
|
if dt == 0 then |
||||||
|
return _ncalls[b] < _ncalls[a] |
||||||
|
end |
||||||
|
return dt < 0 |
||||||
|
end |
||||||
|
|
||||||
|
--- Generates a report of functions that have been called since the profile was started. |
||||||
|
-- Returns the report as a numeric table of rows containing the rank, function label, number of calls, total execution time and source code line number. |
||||||
|
-- @tparam[opt] number limit Maximum number of rows |
||||||
|
-- @treturn table Table of rows |
||||||
|
function profile.query(limit) |
||||||
|
local t = {} |
||||||
|
for f, n in pairs(_ncalls) do |
||||||
|
if n > 0 then |
||||||
|
t[#t + 1] = f |
||||||
|
end |
||||||
|
end |
||||||
|
table.sort(t, profile.comp) |
||||||
|
if limit then |
||||||
|
while #t > limit do |
||||||
|
table.remove(t) |
||||||
|
end |
||||||
|
end |
||||||
|
for i, f in ipairs(t) do |
||||||
|
local dt = 0 |
||||||
|
if _tcalled[f] then |
||||||
|
dt = clock() - _tcalled[f] |
||||||
|
end |
||||||
|
t[i] = { i, _labeled[f] or "?", _ncalls[f], _telapsed[f] + dt, _defined[f] } |
||||||
|
end |
||||||
|
return t |
||||||
|
end |
||||||
|
|
||||||
|
local cols = { 3, 29, 11, 24, 32 } |
||||||
|
|
||||||
|
--- Generates a text report of functions that have been called since the profile was started. |
||||||
|
-- Returns the report as a string that can be printed to the console. |
||||||
|
-- @tparam[opt] number limit Maximum number of rows |
||||||
|
-- @treturn string Text-based profiling report |
||||||
|
function profile.report(n) |
||||||
|
local out = {} |
||||||
|
local report = profile.query(n) |
||||||
|
for i, row in ipairs(report) do |
||||||
|
for j = 1, 5 do |
||||||
|
local s = row[j] |
||||||
|
local l2 = cols[j] |
||||||
|
s = tostring(s) |
||||||
|
local l1 = s:len() |
||||||
|
if l1 < l2 then |
||||||
|
s = s .. (" "):rep(l2 - l1) |
||||||
|
elseif l1 > l2 then |
||||||
|
s = s:sub(l1 - l2 + 1, l1) |
||||||
|
end |
||||||
|
row[j] = s |
||||||
|
end |
||||||
|
out[i] = table.concat(row, " | ") |
||||||
|
end |
||||||
|
|
||||||
|
local row = |
||||||
|
" +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n" |
||||||
|
local col = |
||||||
|
" | # | Function | Calls | Time | Code | \n" |
||||||
|
local sz = row .. col .. row |
||||||
|
if #out > 0 then |
||||||
|
sz = sz .. " | " .. table.concat(out, " | \n | ") .. " | \n" |
||||||
|
end |
||||||
|
return "\n" .. sz .. row |
||||||
|
end |
||||||
|
|
||||||
|
-- store all internal profiler functions |
||||||
|
for _, v in pairs(profile) do |
||||||
|
if type(v) == "function" then |
||||||
|
_internal[v] = true |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
return profile |
Loading…
Reference in new issue