Created
April 28, 2017 21:31
-
-
Save ZeroStride/3485c35e2583e5aca3978d54f2004399 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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