Skip to content

Instantly share code, notes, and snippets.

@ZeroStride
Created April 28, 2017 21:31
Show Gist options
  • Save ZeroStride/3485c35e2583e5aca3978d54f2004399 to your computer and use it in GitHub Desktop.
Save ZeroStride/3485c35e2583e5aca3978d54f2004399 to your computer and use it in GitHub Desktop.
-- http://lua-users.org/wiki/SimpleStats
-- Small stats library --
----------------------------------------------
-- Version History --
-- 1.0 First written.
-- Tables supplied as arguments are not changed.
-- Table to hold statistical functions
stats={}
-- Get the mean value of a table
function stats.mean( t )
local sum = 0
local count= 0
for k,v in pairs(t) do
if type(v) == 'number' then
sum = sum + v
count = count + 1
end
end
return (sum / count)
end
-- Get the mode of a table. Returns a table of values.
-- Works on anything (not just numbers).
function stats.mode( t )
local counts={}
for k, v in pairs( t ) do
if counts[v] == nil then
counts[v] = 1
else
counts[v] = counts[v] + 1
end
end
local biggestCount = 0
for k, v in pairs( counts ) do
if v > biggestCount then
biggestCount = v
end
end
local temp={}
for k,v in pairs( counts ) do
if v == biggestCount then
table.insert( temp, k )
end
end
return temp
end
-- Get the median of a table.
function stats.median( t )
local temp={}
-- deep copy table so that when we sort it, the original is unchanged
-- also weed out any non numbers
for k,v in pairs(t) do
if type(v) == 'number' then
table.insert( temp, v )
end
end
table.sort( temp )
-- If we have an even number of table elements or odd.
if math.fmod(#temp,2) == 0 then
-- return mean value of middle two elements
return ( temp[#temp/2] + temp[(#temp/2)+1] ) / 2
else
-- return middle element
return temp[math.ceil(#temp/2)]
end
end
-- Get the standard deviation of a table
function stats.stddev( t )
local m
local vm
local sum = 0
local count = 0
local result
m = stats.mean( t )
for k,v in pairs(t) do
if type(v) == 'number' then
vm = v - m
sum = sum + (vm * vm)
count = count + 1
end
end
result = math.sqrt(sum / (count-1))
return result
end
-- Get the max and min for a table
function stats.maxmin( t )
local max = -math.huge
local min = math.huge
for k,v in pairs( t ) do
if type(v) == 'number' then
max = math.max( max, v )
min = math.min( min, v )
end
end
return max, min
end
-- Get percentile of a table
function stats.percentile( t, p )
local temp={}
-- deep copy table so that when we sort it, the original is unchanged
-- also weed out any non numbers
for k,v in pairs(t) do
if type(v) == 'number' then
table.insert( temp, v )
end
end
table.sort( temp )
local index = p * #temp
local percentile = temp[math.ceil(index)]
if index == math.ceil( index ) then
percentile = (temp[index] + temp[index + 1]) / 2
end
return percentile
end
return stats
local stats = require('stats')
local counter = 1
local threads = {}
function setup(thread)
thread:set("id", counter)
threads[counter] = thread
counter = counter + 1
end
function init(args)
response_time = {}
c = 1
end
function response(status, headers, body)
response_time[c] = tonumber(string.sub(headers['x-response-time'], 1, -3))
c = c + 1
end
function done(summary, latency, requests)
local response_times = {}
for index, thread in ipairs(threads) do
local responses = thread:get('response_time')
for i = 1, #responses do
response_times[#response_times+1] = responses[i]
end
end
if #response_times > 0 then
local max, min = stats.maxmin(response_times)
print(string.format("\nX-Response-Time Header Metrics"))
print(string.format("Min response time %.02fms", min))
print(string.format("Max response time %.02fms", max))
print(string.format("Mean response time %.02fms", stats.mean(response_times)))
print(string.format("Median response time %.02fms", stats.median(response_times)))
print(string.format("95th percentile %.02fms", stats.percentile(response_times, 0.95)))
print(string.format("99th percentile %.02fms", stats.percentile(response_times, 0.99)))
print(string.format("Standard deviation in response time %.02fms", stats.stddev(response_times)))
else
print("No X-Response-Time headers found in responses")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment