#!/usr/bin/env ruby

LKP_SRC ||= ENV['LKP_SRC'] || File.dirname(__dir__)

require "#{LKP_SRC}/lib/array_ext"

set_sum = 0
set_num = 0
set_avg = 0
get_sum = 0
get_num = 0
get_avg = 0
is_set = true
set_latencies = []
get_latencies = []
proc_set_latencies = nil
proc_get_latencies = nil
set_time = 0
set_time_sum = 0
set_time_num = 0
get_time = 0
get_time_sum = 0
get_time_num = 0

PERCENTILE_STRS = ['90', '95', '99', '99.9'].freeze
PERCENTILES = PERCENTILE_STRS.map(&:to_f)

$stdin.each_line do |line|
  case line
  when /PING_INLINE: (\d+).(\d+) requests per second$/
    puts "PING_INLINE: #{$1}.#{$2}"
  when /PING_BULK: (\d+).(\d+) requests per second$/
    puts "PING_BULK: #{$1}.#{$2}"
  when /====== SET ======$/
    is_set = true
    proc_set_latencies = []
  when /====== GET ======$/
    is_set = false
    proc_get_latencies = []
  when /^(\d+\.\d+) requests per second$/
    if is_set
      set_sum += $1.to_f
      set_num += 1
      set_latencies << proc_set_latencies
    else
      get_sum += $1.to_f
      get_num += 1
      get_latencies << proc_get_latencies
    end
  when /requests completed in (\d+\.\d+) seconds$/
    if is_set
      set_time_sum += $1.to_f
      set_time_num += 1
    else
      get_time_sum += $1.to_f
      get_time_num += 1
    end
  when /^(\d+\.\d+)% <= (\d+) milliseconds$/
    ms = $2.to_i
    if is_set
      proc_set_latencies[ms] = $1.to_f
    else
      proc_get_latencies[ms] = $1.to_f
    end
  when /INCR: (\d+).(\d+) requests per second$/
    puts "INCR: #{$1}.#{$2}"
  when /LPUSH: (\d+).(\d+) requests per second$/
    puts "LPUSH: #{$1}.#{$2}"
  when /RPUSH: (\d+).(\d+) requests per second$/
    puts "RPUSH: #{$1}.#{$2}"
  when /LPOP: (\d+).(\d+) requests per second$/
    puts "LPOP: #{$1}.#{$2}"
  when /RPOP: (\d+).(\d+) requests per second$/
    puts "RPOP: #{$1}.#{$2}"
  when /SADD: (\d+).(\d+) requests per second$/
    puts "SADD: #{$1}.#{$2}"
  when /HSET: (\d+).(\d+) requests per second$/
    puts "HSET: #{$1}.#{$2}"
  when /SPOP: (\d+).(\d+) requests per second$/
    puts "SPOP: #{$1}.#{$2}"
  when /LPUSH .needed to benchmark LRANGE.: (\d+).(\d+) requests per second$/
    puts "LPUSH_LRANGE: #{$1}.#{$2}"
  when /LRANGE_100 .first 100 elements.: (\d+).(\d+) requests per second$/
    puts "LRANGE_100: #{$1}.#{$2}"
  when /LRANGE_300 .first 300 elements.: (\d+).(\d+) requests per second$/
    puts "LRANGE_300: #{$1}.#{$2}"
  when /LRANGE_500 .first 450 elements.: (\d+).(\d+) requests per second$/
    puts "LRANGE_500: #{$1}.#{$2}"
  when /LRANGE_600 .first 600 elements.: (\d+).(\d+) requests per second$/
    puts "LRANGE_600: #{$1}.#{$2}"
  when /MSET .10 keys.: (\d+).(\d+) requests per second$/
    puts "MSET: #{$1}.#{$2}"
  end
end
set_avg = set_num > 0 ? set_sum / set_num : 0
get_avg = get_num > 0 ? get_sum / get_num : 0
set_time = set_time_num > 0 ? set_time_sum / set_time_num : 0
get_time = get_time_num > 0 ? get_time_sum / get_time_num : 0
puts "set_total_throughput_rps: #{set_sum}"
puts "get_total_throughput_rps: #{get_sum}"
puts "set_total_time_sec: #{set_time_sum}"
puts "get_total_time_sec: #{get_time_sum}"
puts "set_avg_throughput_rps: #{set_avg}"
puts "get_avg_throughput_rps: #{get_avg}"
puts "set_avg_time_sec: #{set_time}"
puts "get_avg_time_sec: #{get_time}"

def normalize_latencies(latencies)
  maxcol = latencies.map(&:size).max
  latencies.each do |proc_latencies|
    prev = 0
    (0...maxcol).map do |i|
      percent = proc_latencies[i]
      percent ||= prev
      prev = percent
      proc_latencies[i] = percent
    end
  end
end

def show_latencies(latencies, name)
  pi = 0
  latencies.transpose.each_with_index do |ps, i|
    sum = ps.sum
    next if sum == 0

    avg = sum.to_f / ps.length
    puts "#{name}_latency_#{i}ms%: #{avg}"
    while pi < PERCENTILES.length && avg > PERCENTILES[pi]
      puts "#{name}_latency_#{PERCENTILE_STRS[pi]}%_ms: #{i}"
      pi += 1
    end
    break if avg > PERCENTILES[-1]
  end
end

normalize_latencies(set_latencies)
normalize_latencies(get_latencies)

show_latencies(set_latencies, 'set')
show_latencies(get_latencies, 'get')
