Module: Fasten::Support::Stats
- Included in:
- Runner
- Defined in:
- lib/fasten/support/stats.rb
Constant Summary collapse
- FLOAT_FORMATTER =
->(f) { format('%7.3f', f) }
Instance Method Summary collapse
- #hformat(time, total = nil) ⇒ Object
-
#initialize_stats ⇒ Object
attr_writer :stats_data, :stats_entries attr_reader :stats_path.
- #load_stats ⇒ Object
- #save_stats ⇒ Object
- #split_time(time) ⇒ Object
- #stats_add_entry(state, target) ⇒ Object
- #stats_create_entry(state, target) ⇒ Object
- #stats_data ⇒ Object
- #stats_entries ⇒ Object
- #stats_last(target) ⇒ Object
- #stats_run_history(entry) ⇒ Object
- #stats_summary ⇒ Object
- #stats_summary_data ⇒ Object
- #update_stats(history, entry) ⇒ Object
Instance Method Details
#hformat(time, total = nil) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/fasten/support/stats.rb', line 106 def hformat(time, total = nil) sign, hours, mins, secs, msecs = split_time time str = hours.zero? ? format('%.1s%02d:%02d.%03d', sign, mins, secs, msecs) : format('%.1s%02d:%02d:%02d.%03d', sign, hours, mins, secs, msecs) str += format(' (%.1f%%)', 100.0 * time / total) if total str end |
#initialize_stats ⇒ Object
attr_writer :stats_data, :stats_entries attr_reader :stats_path
11 12 13 14 15 16 17 18 |
# File 'lib/fasten/support/stats.rb', line 11 def initialize_stats return unless stats @stats_path = "#{ENV['HOME']}/.fasten/stats/#{name}.csv" if ENV['HOME'] FileUtils.mkdir_p File.dirname(@stats_path) rescue StandardError @stats_path = nil end |
#load_stats ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/fasten/support/stats.rb', line 20 def load_stats return unless @stats_path && File.exist?(@stats_path) @stats_data = [] CSV.foreach(@stats_path, headers: true, converters: [:all]) do |row| stats_data << row.to_h end @tasks.each do |task| task.runner = self task.last_stat end self.runner = self last_stat @tasks.waiting = nil rescue StandardError nil end |
#save_stats ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/fasten/support/stats.rb', line 40 def save_stats return unless @stats_path && stats_data keys = %w[state kind name run cnt avg std err ini fin deps] CSV.open(@stats_path, 'wb') do |csv| csv << keys stats_data.each do |data| csv << keys.map { |i| data[i] } end end end |
#split_time(time) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/fasten/support/stats.rb', line 94 def split_time(time) sign = time.negative? ? '-' : '' time = -time if time.negative? hours, seconds = time.divmod(3600) minutes, seconds = seconds.divmod(60) seconds, decimal = seconds.divmod(1) milliseconds, _ignored = (decimal.round(4) * 1000).divmod(1) [sign, hours, minutes, seconds, milliseconds] end |
#stats_add_entry(state, target) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/fasten/support/stats.rb', line 73 def stats_add_entry(state, target) return unless target.ini && target.fin entry = stats_create_entry(state, target) stats_data << entry stats_entries << entry history = stats_run_history(entry) update_stats(history, entry) end |
#stats_create_entry(state, target) ⇒ Object
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/fasten/support/stats.rb', line 54 def stats_create_entry(state, target) { 'state' => state.to_s, 'kind' => target.kind, 'name' => target.name, 'ini' => target.ini.to_f, 'fin' => target.fin.to_f, 'run' => target.fin - target.ini, 'deps' => target.deps, 'worker' => target.respond_to?(:worker) ? target.worker.name : nil } end |
#stats_data ⇒ Object
65 66 67 |
# File 'lib/fasten/support/stats.rb', line 65 def stats_data @stats_data ||= [] end |
#stats_entries ⇒ Object
69 70 71 |
# File 'lib/fasten/support/stats.rb', line 69 def stats_entries @stats_entries ||= [] end |
#stats_last(target) ⇒ Object
131 132 133 |
# File 'lib/fasten/support/stats.rb', line 131 def stats_last(target) stats_data.select { |item| %w[kind name deps].all? { |key| item[key] == target.send(key) } }.last || {} end |
#stats_run_history(entry) ⇒ Object
127 128 129 |
# File 'lib/fasten/support/stats.rb', line 127 def stats_run_history(entry) stats_data.select { |item| %w[state kind name deps].all? { |key| item[key] == entry[key] } }.map { |item| item['run'] } end |
#stats_summary ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/fasten/support/stats.rb', line 115 def stats_summary sub, tot = stats_summary_data Hirb::Console.render_output(stats_entries, fields: %w[state kind name run cnt avg std err worker], unicode: true, class: 'Hirb::Helpers::AutoTable', filters: { 'run' => FLOAT_FORMATTER, 'avg' => FLOAT_FORMATTER, 'std' => FLOAT_FORMATTER, 'err' => FLOAT_FORMATTER }, description: false) puts format('∑tasks: %<task>s runner: %<runner>s saved: %<saved>s jobs: %<jobs>s', task: hformat(sub), runner: hformat(tot, sub), saved: hformat(sub - tot, sub), jobs: jobs.to_s) end |
#stats_summary_data ⇒ Object
87 88 89 90 91 92 |
# File 'lib/fasten/support/stats.rb', line 87 def stats_summary_data sub = stats_entries.select { |x| x['kind'] == 'task' }.map { |x| x['run'] }.sum tot = stats_entries.select { |x| x['kind'] == 'runner' }.map { |x| x['run'] }.sum [sub, tot] end |
#update_stats(history, entry) ⇒ Object
135 136 137 138 139 140 |
# File 'lib/fasten/support/stats.rb', line 135 def update_stats(history, entry) entry['cnt'] = cnt = history.size entry['avg'] = avg = history.sum.to_f / cnt entry['std'] = std = Math.sqrt(history.map { |x| (x - avg)**2 }.sum / cnt) entry['err'] = std / Math.sqrt(cnt) if cnt.positive? end |