|
require 'bundler/inline' |
|
|
|
gemfile do |
|
gem 'activesupport' |
|
gem 'markdown-tables' |
|
end |
|
|
|
require 'json' |
|
require 'active_support/all' |
|
|
|
path = ARGV.first |
|
|
|
class Request |
|
attr_reader :gc_ms, :run_ms, :idle_ms, :stall_ms, :io_percent, :method, :action |
|
|
|
def initialize(hash) |
|
@gc_ms = hash[:gc_ms] |
|
@run_ms = hash[:run_ms] |
|
@idle_ms = hash[:idle_ms] |
|
@stall_ms = hash[:stall_ms] |
|
@io_percent = hash[:io_percent] |
|
@method = hash[:method] |
|
@action = hash[:action] |
|
end |
|
|
|
def total_ms |
|
@run_ms + @idle_ms + @stall_ms |
|
end |
|
end |
|
|
|
requests = [] |
|
File.open(path).each_line do |line| |
|
requests << Request.new(JSON.parse(line, symbolize_names: true, freeze: true)) |
|
end |
|
|
|
puts "Data set: https://gist.github.com/byroot/e1fcfd1f8e172f5d9c5bfecefebdb15f#file-production-gvl-log" |
|
puts |
|
|
|
print "total io%: " |
|
total_run_ms = requests.sum(&:run_ms) |
|
total_idle_ms = requests.sum(&:idle_ms) |
|
puts ((total_idle_ms / (total_run_ms + total_idle_ms)) * 100.0).round(2) |
|
puts |
|
|
|
print "total io and stall%: " |
|
total_stall_ms = requests.sum(&:stall_ms) |
|
puts (((total_idle_ms + total_stall_ms) / (total_run_ms + total_idle_ms + total_stall_ms)) * 100.0).round(2) |
|
puts |
|
|
|
print "average response time ms: " |
|
puts ((total_stall_ms + total_run_ms + total_idle_ms) / requests.size).round(2) |
|
puts |
|
|
|
print "average stall ms: " |
|
puts (total_stall_ms / requests.size).round(2) |
|
puts |
|
puts |
|
|
|
puts '-' * 10 |
|
|
|
def avg(data, &block) |
|
data.sum(&block) / data.size |
|
end |
|
|
|
def row(name, group) |
|
io_percent = (group.sum(&:idle_ms) / (group.sum(&:run_ms) + group.sum(&:idle_ms))) * 100.0 |
|
[ |
|
name, |
|
avg(group, &:run_ms).round(1), |
|
avg(group, &:idle_ms).round(1), |
|
avg(group, &:stall_ms).round(1), |
|
avg(group, &:total_ms).round(1), |
|
"#{io_percent.round(1)}%", |
|
group.size, |
|
] |
|
end |
|
|
|
def compute_percentiles(action, requests) |
|
puts "### #{action || 'rack middleware'} #{requests.size} requests" |
|
puts |
|
|
|
requests.sort_by!(&:total_ms) |
|
|
|
decile = ((requests.size / 10.0).ceil) |
|
first_decile = requests[0..decile] |
|
mid_decile = requests[(5*decile)..(6*decile)] |
|
last_decile = requests[(9 * decile)..-1] |
|
percentile = decile / 10 |
|
last_percentile = last_decile.slice!((-percentile)..-1) |
|
mill = percentile / 10 |
|
last_mill = last_percentile.slice!((-mill)..-1) |
|
|
|
labels = [action, "cpu", "io", "GVL", "total", "io%", "count"] |
|
|
|
rows = [ |
|
row("p0-10", first_decile), |
|
row("p50-60", mid_decile), |
|
row("p90-99", last_decile), |
|
row("p99-99.9", last_percentile), |
|
row("p99.9-100", last_mill), |
|
] |
|
|
|
puts MarkdownTables.make_table(labels, rows, is_rows: true) |
|
puts |
|
puts |
|
end |
|
|
|
compute_percentiles("overall", requests) |
|
|
|
requests_by_action = requests.group_by(&:action).sort_by { |_a, r| -r.size } |
|
requests_by_action.first(5).each do |action, requests| |
|
compute_percentiles(action, requests) |
|
end |