Skip to content

Commit

Permalink
[wip] optimize benchmark-ips to be more JITable
Browse files Browse the repository at this point in the history
  • Loading branch information
mikz committed May 28, 2018
1 parent e11df2f commit fb0ad98
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 5 deletions.
31 changes: 26 additions & 5 deletions benchmark/ips.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ local Timing = { }


local ffi = require 'ffi'
local tab_new = require "table.new"

ffi.cdef [[
typedef int clockid_t;
Expand All @@ -17,8 +18,10 @@ struct timespec {
};

int clock_gettime(clockid_t clk_id, struct timespec *tp);
char *strerror(int errnum);
]]

local C = ffi.C

local CLOCK = {
REALTIME = 0,
Expand All @@ -32,10 +35,16 @@ local CLOCK = {

local ts = ffi.new("struct timespec[1]")

local function ffi_error()
return C.strerror(ffi.errno())
end

-- Get an object that represents now in nanoseconds
function Timing.now()
assert(ffi.C.clock_gettime(clock or CLOCK.MONOTONIC_RAW, ts) == 0,
"clock_gettime() failed: "..ffi.errno())
if C.clock_gettime(CLOCK.MONOTONIC_RAW, ts) ~= 0 then
return nil, ffi_error()
end

return tonumber(ts[0].tv_sec * 1e9 + ts[0].tv_nsec)
end

Expand Down Expand Up @@ -229,6 +238,16 @@ local map = function(t, f)
return m
end

local function stats_samples(measurements_ns, cycles)
local samples = tab_new(#measurements_ns, 0)

for i, time_ns in ipairs(measurements_ns) do
samples[i] = iterations_per_sec(cycles, time_ns)
end

return samples
end

function IPS:run_benchmark()
for _,item in ipairs(self.items) do
self:notify('running', item.label, self.time)
Expand Down Expand Up @@ -266,8 +285,7 @@ function IPS:run_benchmark()

local final_time = after
local measured_ns = sum(measurements_ns)
local samples = map(measurements_ns, function(time_ns) return iterations_per_sec(cycles, time_ns) end)

local samples = stats_samples(measurements_ns, cycles)
local rep = self.full_report:add_entry(item.label, measured_ns, iter, Stats:new(samples), cycles)

self:notify('report_entry', rep)
Expand Down Expand Up @@ -353,7 +371,10 @@ end

local function stat_variance(samples, m)
local mean = m or stat_mean(samples)
local total = sum(map(samples, function(n) return math.pow(n - mean, 2) end))
local total = 0
for _,n in ipairs(samples) do
total = total + math.pow(n - mean, 2)
end

return total / #samples
end
Expand Down
88 changes: 88 additions & 0 deletions benchmark/regexpify.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
local re_gsub = ngx.re.gsub

require('resty.core')
require('benchmark.ips')(function(b)
b.time = 5
b.warmup = 2

local gsub = string.gsub

local ffi_re_gsub = ngx.re.gsub

local transforms = {
{ '?.*', '' },
{ "{.-}", [[([\w-.~%%!$&'()*+,;=@:]+)]] },
{ "%.", [[\.]] },
}

local function loop(pattern)
for i=1, #transforms do
pattern = gsub(pattern, transforms[i][1], transforms[i][2])
end
return pattern
end

local function closure(pattern)
pattern = gsub(pattern, '?.*', '')
pattern = gsub(pattern, "{.-}", [[([\w-.~%%!$&'()*+,;=@:]+)]])
pattern = gsub(pattern, "%.", "\\.")

return pattern
end

local function global(pattern)
-- as per the RFC: https://tools.ietf.org/html/rfc3986#section-3.3
local wildcard_regex = [[([\w-.~%%!$&'()*+,;=@:]+)]] -- using long Lua brackets [[...]], escaping `%`
return pattern:gsub('?.*', ''):gsub("{.-}", wildcard_regex):gsub("%.", "\\.")
end

local function pcre(pattern)
pattern = re_gsub(pattern, [[\?.*]], '')
pattern = re_gsub(pattern, [[\{.+?\}]], [[([\w-.~%!$$&'()*+,;=@:]+)]])
pattern = re_gsub(pattern, [[\.]], [[\.]])

return pattern
end

local function pcre_jit(pattern)
pattern = re_gsub(pattern, [[\?.*]], '', 'oj')
pattern = re_gsub(pattern, [[\{.+?\}]], [[([\w-.~%!$$&'()*+,;=@:]+)]], 'oj')
pattern = re_gsub(pattern, [[\.]], [[\.]], 'oj')

return pattern
end

local function ffi_pcre(pattern)
pattern = ffi_re_gsub(pattern, [[\?.*]], '')
pattern = ffi_re_gsub(pattern, [[\{.+?\}]], [[([\w-.~%!$$&'()*+,;=@:]+)]])
pattern = ffi_re_gsub(pattern, [[\.]], [[\.]])

return pattern
end

local function ffi_pcre_jit(pattern)
pattern = ffi_re_gsub(pattern, [[\?.*]], '', 'oj')
pattern = ffi_re_gsub(pattern, [[\{.+?\}]], [[([\w-.~%!$$&'()*+,;=@:]+)]], 'oj')
pattern = ffi_re_gsub(pattern, [[\.]], [[\.]], 'oj')

return pattern
end

local str = '/tfgoodosod/{foo}/sdsd?asdasdd'

print('loop: ' , loop(str))
print('closure:' , closure(str))
print('global: ' , global(str))
print('pcre: ' , pcre(str))

b:report('loop', function() return loop(str) end)
b:report('gsub', function() return closure(str) end)
b:report('string.gsub', function() return global(str) end)
b:report('re.gsub', function() return pcre(str) end)
b:report('re.gsub jit', function() return pcre_jit(str) end)

b:report('ffi re.gsub', function() return ffi_pcre(str) end)
b:report('ffi re.gsub jit', function() return ffi_pcre_jit(str) end)

b:compare()
end)

0 comments on commit fb0ad98

Please sign in to comment.