You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.4 KiB
170 lines
4.4 KiB
--[[
|
|
|
|
Profiler functions
|
|
|
|
LuaProfiler is desync unsafe so you cannot use it in multiplayer.
|
|
|
|
Prints summary to log file and to console every 5 seconds.
|
|
|
|
|
|
Example 1:
|
|
Profiler.start('test1')
|
|
...code...
|
|
Profiler.split('test1','chunk1') -- optional
|
|
...code...
|
|
Profiler.split('test1','chunk2') -- optional
|
|
...code...
|
|
Profiler.stop('test1')
|
|
|
|
Example 2:
|
|
Profiler.start('test2', table_size(items))
|
|
for _, item in pairs(items) do
|
|
...code...
|
|
end
|
|
Profiler.stop('test2')
|
|
|
|
Example 3:
|
|
Profiler.count('counter1')
|
|
|
|
]]--
|
|
|
|
local Profiler = {
|
|
enabled = false,
|
|
print_to_console = true
|
|
}
|
|
|
|
if is_debug_mode and Profiler.enabled then
|
|
local active_profilers = {}
|
|
local active_splits = {}
|
|
local active_counters = {}
|
|
|
|
-- LuaProfiler makes the game slower as more and more profilers are created,
|
|
-- thus we create a pool of profilers to mitigate the issue
|
|
local profilers_pool = {}
|
|
local profilers_used = {}
|
|
|
|
local function get_make_profiler()
|
|
local profiler
|
|
if table_size(profilers_pool) > 0 then
|
|
profiler = table.remove(profilers_pool)
|
|
profiler.reset()
|
|
else
|
|
profiler = game.create_profiler(true)
|
|
end
|
|
table.insert(profilers_used, profiler)
|
|
return profiler
|
|
end
|
|
|
|
local function recycle_profilers()
|
|
for _, profiler in pairs(profilers_used) do
|
|
table.insert(profilers_pool, profiler)
|
|
end
|
|
profilers_used = {}
|
|
end
|
|
|
|
local function dup_profiler(profiler)
|
|
local new_profiler = get_make_profiler()
|
|
new_profiler.reset()
|
|
new_profiler.stop()
|
|
new_profiler.add(profiler)
|
|
return new_profiler
|
|
end
|
|
|
|
|
|
function Profiler.start(name, unit_count)
|
|
if not active_profilers[name] then
|
|
active_profilers[name] = {
|
|
profiler = get_make_profiler(),
|
|
tick = game.tick,
|
|
count = 0
|
|
}
|
|
end
|
|
if unit_count == nil then unit_count = 1 end
|
|
active_profilers[name].count = active_profilers[name].count + unit_count
|
|
active_profilers[name].profiler.restart()
|
|
end
|
|
|
|
function Profiler.stop(name)
|
|
if active_profilers[name] then
|
|
if active_splits[name] then
|
|
Profiler.stop(active_splits[name])
|
|
active_splits[name] = nil
|
|
end
|
|
active_profilers[name].profiler.stop()
|
|
end
|
|
end
|
|
|
|
function Profiler.split(name, part)
|
|
if active_profilers[name] then
|
|
if active_splits[name] then
|
|
Profiler.stop(active_splits[name])
|
|
active_splits[name] = nil
|
|
end
|
|
if part then
|
|
local split_name = name .. "--" .. part
|
|
Profiler.start(split_name)
|
|
active_splits[name] = split_name
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function Profiler.count(name, value)
|
|
if not active_counters[name] then
|
|
active_counters[name] = {
|
|
counter = 0,
|
|
tick = game.tick
|
|
}
|
|
end
|
|
if value == nil then value = 1 end
|
|
active_counters[name].counter = active_counters[name].counter + value
|
|
end
|
|
|
|
function Profiler.collect_print()
|
|
local results = {}
|
|
for name, entry in pairs(active_profilers) do
|
|
entry.profiler.stop()
|
|
if entry.count == 0 then
|
|
entry.profiler.divide(game.tick - entry.tick + 1)
|
|
results[name] = { "", "PerTick ", entry.profiler }
|
|
else
|
|
local per_tick_count = entry.count / (game.tick - entry.tick + 1)
|
|
local per_unit_profiler = dup_profiler(entry.profiler)
|
|
per_unit_profiler.divide(entry.count)
|
|
entry.profiler.divide(game.tick - entry.tick + 1)
|
|
results[name] = { "", "PerUnit (", per_tick_count, "/", entry.count, ") ", per_unit_profiler,
|
|
" / PerTick ", entry.profiler }
|
|
end
|
|
end
|
|
for name, entry in pairs(active_counters) do
|
|
local value = entry.counter / (game.tick - entry.tick + 1)
|
|
local key = results[name] and (name .. "-count") or name
|
|
results[key] = { "", "Count: ", value }
|
|
end
|
|
|
|
local log_fn = Profiler.print_to_console and Log.trace or Log.debug_log
|
|
-- sort the results
|
|
local keys = {}
|
|
for k in pairs(results) do table.insert(keys, k) end
|
|
table.sort(keys)
|
|
-- print
|
|
log_fn('---')
|
|
for _, name in pairs(keys) do
|
|
log_fn({ "", name, ": ", results[name]})
|
|
end
|
|
-- cleanup
|
|
active_profilers = {}
|
|
active_splits = {}
|
|
active_counters = {}
|
|
recycle_profilers()
|
|
end
|
|
Event.addListener("on_nth_tick_301", Profiler.collect_print) -- 5 seconds
|
|
else
|
|
Profiler.start = function() end
|
|
Profiler.stop = function() end
|
|
Profiler.split = function() end
|
|
Profiler.count = function() end
|
|
Profiler.collect_print = function() end
|
|
end
|
|
|
|
return Profiler
|
|
|