123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- local setmetatable = setmetatable
- local pairs, format = pairs, string.format
- local min, max, huge = math.min, math.max, math.huge
- local core = core
- local profiler = ...
- local sampler = {}
- local profile
- local stats_total
- local logged_time, logged_data
- local _stat_mt = {
- get_time_avg = function(self)
- return self.time_all/self.samples
- end,
- get_part_avg = function(self)
- if not self.part_all then
- return 100
- end
- return self.part_all/self.samples
- end,
- }
- _stat_mt.__index = _stat_mt
- function sampler.reset()
-
-
- logged_time = 0
-
- logged_data = {}
- profile = {
-
-
- stats = {},
-
- stats_total = setmetatable({
- samples = 0,
- time_min = huge,
- time_max = 0,
- time_all = 0,
- part_min = 100,
- part_max = 100
- }, _stat_mt)
- }
- stats_total = profile.stats_total
-
- sampler.profile = profile
- end
- function sampler.log(modname, instrument_name, time_diff)
- if time_diff <= 0 then
- if time_diff < 0 then
-
-
- core.log("warning", format(
- "Time travel of %s::%s by %dµs.",
- modname, instrument_name, time_diff
- ))
- end
-
- return
- end
- local mod_data = logged_data[modname]
- if mod_data == nil then
- mod_data = {}
- logged_data[modname] = mod_data
- end
- mod_data[instrument_name] = (mod_data[instrument_name] or 0) + time_diff
-
- logged_time = logged_time + time_diff
- end
- local function get_statistic(stats_table, name)
- local statistic = stats_table[name]
- if statistic == nil then
- statistic = setmetatable({
- samples = 0,
- time_min = huge,
- time_max = 0,
- time_all = 0,
- part_min = 100,
- part_max = 0,
- part_all = 0,
- }, _stat_mt)
- stats_table[name] = statistic
- end
- return statistic
- end
- local function update_statistic(stats_table, time)
- stats_table.samples = stats_table.samples + 1
-
- stats_table.time_min = min(stats_table.time_min, time)
- stats_table.time_max = max(stats_table.time_max, time)
- stats_table.time_all = stats_table.time_all + time
-
- local current_part = (time/logged_time) * 100
- stats_table.part_min = min(stats_table.part_min, current_part)
- stats_table.part_max = max(stats_table.part_max, current_part)
- stats_table.part_all = stats_table.part_all + current_part
- end
- local function sample(dtime)
-
- if logged_time == 0 then
- return
- end
- for modname, instruments in pairs(logged_data) do
- local mod_stats = get_statistic(profile.stats, modname)
- if mod_stats.instruments == nil then
-
- mod_stats.instruments = {}
- end
- local mod_time = 0
- for instrument_name, time in pairs(instruments) do
- if time > 0 then
- mod_time = mod_time + time
- local instrument_stats = get_statistic(mod_stats.instruments, instrument_name)
-
- update_statistic(instrument_stats, time)
-
- instruments[instrument_name] = 0
- end
- end
-
- update_statistic(mod_stats, mod_time)
- end
-
- stats_total.time_min = min(stats_total.time_min, logged_time)
- stats_total.time_max = max(stats_total.time_max, logged_time)
- stats_total.time_all = stats_total.time_all + logged_time
- stats_total.samples = stats_total.samples + 1
- logged_time = 0
- end
- function sampler.init()
- sampler.reset()
- if core.settings:get_bool("instrument.profiler") then
- core.register_globalstep(function()
- if logged_time == 0 then
- return
- end
- return profiler.empty_instrument()
- end)
- core.register_globalstep(profiler.instrument {
- func = sample,
- mod = "*profiler*",
- class = "Sampler (update stats)",
- label = false,
- })
- else
- core.register_globalstep(sample)
- end
- end
- return sampler
|