Skip to content

Commit 42fbfd4

Browse files
authored
perf: Added benchmark test and limited expression compiling to once unless required (#80)
* feat: Added benchmark tests Signed-off-by: Rushikesh Tote <rushi.tote@gmail.com> * perf: expression will not be recompiled every time Signed-off-by: Rushikesh Tote <rushi.tote@gmail.com>
1 parent a72b822 commit 42fbfd4

File tree

3 files changed

+318
-6
lines changed

3 files changed

+318
-6
lines changed

.github/workflows/build.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,40 @@ jobs:
7777
luacov-coveralls -i src -e .luarocks
7878
env:
7979
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80+
81+
benchmark:
82+
runs-on: ubuntu-latest
83+
strategy:
84+
fail-fast: false
85+
86+
name: Benchmark
87+
88+
steps:
89+
- name: Checkout
90+
uses: actions/checkout@v2
91+
92+
- name: Set up LuaJIT
93+
uses: leafo/gh-actions-lua@v8.0.0
94+
with:
95+
luaVersion: "luajit"
96+
97+
- name: Set up luarocks
98+
uses: leafo/gh-actions-luarocks@v4.0.0
99+
100+
- name: Install PCRE
101+
run: |
102+
sudo apt-get update
103+
sudo apt-get install libpcre3 libpcre3-dev
104+
105+
- name: Install dependencies
106+
run: |
107+
luarocks install lualogging
108+
luarocks install lrexlib-pcre
109+
luarocks install luaposix
110+
luarocks install luasocket
111+
luarocks install busted
112+
luarocks install busted-htest
113+
114+
- name: Run Benchmark
115+
run: |
116+
busted bench.lua -o htest

bench.lua

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
local socket = require("socket")
2+
require("src.main.Enforcer")
3+
local path = os.getenv("PWD") or io.popen("cd"):read()
4+
5+
local function rawEnforce(sub, obj, act)
6+
local policy = {{"alice", "data1", "read"}, {"bob", "data2", "write"}}
7+
for _, rule in pairs(policy) do
8+
if rule[1] == sub and rule[2] == obj and rule[3] == act then
9+
return true
10+
end
11+
end
12+
return false
13+
end
14+
15+
local function benchmarkRaw()
16+
local x = socket.gettime()*1000
17+
for i = 1, 10000 do
18+
rawEnforce("alice", "data1", "read")
19+
end
20+
x = socket.gettime()*1000 - x
21+
return x, 10000
22+
end
23+
24+
local function benchmarkBasicModel()
25+
local e = Enforcer:new(path .. "/examples/basic_model.conf", path .. "/examples/basic_policy.csv")
26+
e:enableLog(false)
27+
local x = socket.gettime()*1000
28+
for i = 1, 10000 do
29+
_ = e:enforce("alice", "data1", "read")
30+
end
31+
x = socket.gettime()*1000 - x
32+
return x, 10000
33+
end
34+
35+
local function benchmarkRBACModel()
36+
local e = Enforcer:new(path .. "/examples/rbac_model.conf", path .. "/examples/rbac_policy.csv")
37+
e:enableLog(false)
38+
local x = socket.gettime()*1000
39+
for i = 1, 10000 do
40+
_ = e:enforce("alice", "data2", "read")
41+
end
42+
x = socket.gettime()*1000 - x
43+
return x, 10000
44+
end
45+
46+
local function benchmarkRBACModelSmall()
47+
local e = Enforcer:new(path .. "/examples/rbac_model.conf", path .. "/examples/empty_policy.csv")
48+
e:enableLog(false)
49+
50+
local pPolicies = {}
51+
-- 100 roles, 10 resources.
52+
for i = 1, 100 do
53+
table.insert(pPolicies, {"group"..tostring(i), "data"..tostring(i%10), "read"})
54+
end
55+
56+
e:AddPolicies(pPolicies)
57+
58+
-- 1000 users.
59+
local gPolicies = {}
60+
for i = 1, 1000 do
61+
table.insert(gPolicies, {"user"..tostring(i), "group"..tostring(i%10)})
62+
end
63+
64+
e:AddGroupingPolicies(gPolicies)
65+
66+
local x = socket.gettime()*1000
67+
for i = 1, 1000 do
68+
_ = e:enforce("user501", "data9", "read")
69+
end
70+
x = socket.gettime()*1000 - x
71+
return x, 1000
72+
end
73+
74+
local function benchmarkRBACModelMedium()
75+
local e = Enforcer:new(path .. "/examples/rbac_model.conf", path .. "/examples/empty_policy.csv")
76+
e:enableLog(false)
77+
78+
local pPolicies = {}
79+
-- 1000 roles, 100 resources.
80+
for i = 1, 1000 do
81+
table.insert(pPolicies, {"group"..tostring(i), "data"..tostring(i%100), "read"})
82+
end
83+
84+
e:AddPolicies(pPolicies)
85+
86+
local gPolicies = {}
87+
-- 10000 users.
88+
for i = 1, 10000 do
89+
table.insert(gPolicies, {"user"..tostring(i), "group"..tostring(i%10)})
90+
end
91+
92+
e:AddGroupingPolicies(gPolicies)
93+
94+
local x = socket.gettime()*1000
95+
for i = 1, 100 do
96+
_ = e:enforce("user5001", "data99", "read")
97+
end
98+
x = socket.gettime()*1000 - x
99+
return x, 100
100+
end
101+
102+
local function benchmarkRBACModelLarge()
103+
local e = Enforcer:new(path .. "/examples/rbac_model.conf", path .. "/examples/empty_policy.csv")
104+
e:enableLog(false)
105+
106+
local pPolicies = {}
107+
-- 10000 roles, 1000 resources.
108+
for i = 1, 10000 do
109+
table.insert(pPolicies, {"group"..tostring(i), "data"..tostring(i%1000), "read"})
110+
end
111+
112+
e:AddPolicies(pPolicies)
113+
114+
local gPolicies = {}
115+
-- 100000 users.
116+
for i = 1, 100000 do
117+
table.insert(gPolicies, {"user"..tostring(i), "group"..tostring(i%10)})
118+
end
119+
120+
e:AddGroupingPolicies(gPolicies)
121+
122+
local x = socket.gettime()*1000
123+
for i = 1, 10 do
124+
_ = e:enforce("user50001", "data999", "read")
125+
end
126+
x = socket.gettime()*1000 - x
127+
return x, 10
128+
end
129+
130+
local function benchmarkRBACModelWithResourceRoles()
131+
local e = Enforcer:new(path .. "/examples/rbac_with_resource_roles_model.conf", path .. "/examples/rbac_with_resource_roles_policy.csv")
132+
e:enableLog(false)
133+
local x = socket.gettime()*1000
134+
for i = 1, 1000 do
135+
_ = e:enforce("alice", "data1", "read")
136+
end
137+
x = socket.gettime()*1000 - x
138+
return x, 1000
139+
end
140+
141+
local function benchmarkRBACModelWithDomains()
142+
local e = Enforcer:new(path .. "/examples/rbac_with_domains_model.conf", path .. "/examples/rbac_with_domains_policy.csv")
143+
e:enableLog(false)
144+
local x = socket.gettime()*1000
145+
for i = 1, 1000 do
146+
_ = e:enforce("alice", "domain1", "data1", "read")
147+
end
148+
x = socket.gettime()*1000 - x
149+
return x, 1000
150+
end
151+
152+
local function benchmarkABACModel()
153+
local e = Enforcer:new(path .. "/examples/abac_model.conf", path .. "/examples/empty_policy.csv")
154+
e:enableLog(false)
155+
156+
local data1 = {["Name"] = "data1", ["Owner"] = "alice"}
157+
158+
local x = socket.gettime()*1000
159+
for i = 1, 1000 do
160+
_ = e:enforce("alice", data1, "read")
161+
end
162+
x = socket.gettime()*1000 - x
163+
return x, 1000
164+
end
165+
166+
local function benchmarkKeyMatchModel()
167+
local e = Enforcer:new(path .. "/examples/keymatch_model.conf", path .. "/examples/keymatch_policy.csv")
168+
e:enableLog(false)
169+
local x = socket.gettime()*1000
170+
for i = 1, 1000 do
171+
_ = e:enforce("alice", "/alice_data/resource1", "GET")
172+
end
173+
x = socket.gettime()*1000 - x
174+
return x, 1000
175+
end
176+
177+
local function benchmarkRBACModelWithDeny()
178+
local e = Enforcer:new(path .. "/examples/rbac_with_deny_model.conf", path .. "/examples/rbac_with_deny_policy.csv")
179+
e:enableLog(false)
180+
local x = socket.gettime()*1000
181+
for i = 1, 1000 do
182+
_ = e:enforce("alice", "data1", "read")
183+
end
184+
x = socket.gettime()*1000 - x
185+
return x, 1000
186+
end
187+
188+
local function benchmarkPriorityModel()
189+
local e = Enforcer:new(path .. "/examples/priority_model.conf", path .. "/examples/priority_policy.csv")
190+
e:enableLog(false)
191+
local x = socket.gettime()*1000
192+
for i = 1, 1000 do
193+
_ = e:enforce("alice", "data1", "read")
194+
end
195+
x = socket.gettime()*1000 - x
196+
return x, 1000
197+
end
198+
199+
local function runBenchmark()
200+
local t, o
201+
local time = {}
202+
local ops = {}
203+
local benchName = {}
204+
205+
t, o = benchmarkRaw()
206+
table.insert(time, t)
207+
table.insert(ops, o)
208+
table.insert(benchName, "Raw")
209+
210+
t, o = benchmarkBasicModel()
211+
table.insert(time, t)
212+
table.insert(ops, o)
213+
table.insert(benchName, "Basic Model")
214+
215+
t, o = benchmarkRBACModel()
216+
table.insert(time, t)
217+
table.insert(ops, o)
218+
table.insert(benchName, "RBAC Model")
219+
220+
t, o = benchmarkRBACModelSmall()
221+
table.insert(time, t)
222+
table.insert(ops, o)
223+
table.insert(benchName, "RBAC Model Small")
224+
225+
t, o = benchmarkRBACModelMedium()
226+
table.insert(time, t)
227+
table.insert(ops, o)
228+
table.insert(benchName, "RBAC Model Medium")
229+
230+
t, o = benchmarkRBACModelLarge()
231+
table.insert(time, t)
232+
table.insert(ops, o)
233+
table.insert(benchName, "RBAC Model Large")
234+
235+
t, o = benchmarkRBACModelWithResourceRoles()
236+
table.insert(time, t)
237+
table.insert(ops, o)
238+
table.insert(benchName, "RBAC Model with Resources")
239+
240+
t, o = benchmarkRBACModelWithDomains()
241+
table.insert(time, t)
242+
table.insert(ops, o)
243+
table.insert(benchName, "RBAC Model with Domains")
244+
245+
t, o = benchmarkABACModel()
246+
table.insert(time, t)
247+
table.insert(ops, o)
248+
table.insert(benchName, "ABAC Model")
249+
250+
t, o = benchmarkKeyMatchModel()
251+
table.insert(time, t)
252+
table.insert(ops, o)
253+
table.insert(benchName, "KeyMatch Model")
254+
255+
t, o = benchmarkRBACModelWithDeny()
256+
table.insert(time, t)
257+
table.insert(ops, o)
258+
table.insert(benchName, "RBAC Model with Deny")
259+
260+
t, o = benchmarkPriorityModel()
261+
table.insert(time, t)
262+
table.insert(ops, o)
263+
table.insert(benchName, "Priority Model")
264+
265+
print("Benchmark:")
266+
for k, v in pairs(benchName) do
267+
print(v .. ":", "\tTotal ops = " .. tostring(ops[k]), "\tTime per op = " .. string.format("%.4f ms", time[k]/ops[k]))
268+
end
269+
end
270+
271+
runBenchmark()

src/main/CoreEnforcer.lua

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ function CoreEnforcer:enforceEx(...)
370370

371371
local policyEffects = {}
372372

373+
expString = Util.replaceInOfMatcher(expString)
374+
local compiledExpression = luaxp.compile(expString)
375+
373376
if policyLen ~=0 then
374377
for i, pvals in pairs(self.model.model["p"]["p"].policy) do
375378
if #pTokens ~= #pvals then
@@ -388,9 +391,13 @@ function CoreEnforcer:enforceEx(...)
388391
end
389392

390393
local tExpString = Util.findAndReplaceEval(expString, context)
391-
tExpString = Util.replaceInOfMatcher(tExpString)
392394

393-
local res, err = luaxp.evaluate(tExpString, context)
395+
local res, err
396+
if tExpString == expString then
397+
res, err = luaxp.run(compiledExpression, context)
398+
else
399+
res, err = luaxp.evaluate(tExpString, context)
400+
end
394401
if err then
395402
error("evaluation error: " .. err.message)
396403
end
@@ -434,11 +441,8 @@ function CoreEnforcer:enforceEx(...)
434441
for k, v in pairs(pTokens) do
435442
context[v] = ""
436443
end
437-
438-
local tExpString = expString
439-
tExpString = Util.replaceInOfMatcher(tExpString)
440444

441-
local res, err = luaxp.evaluate(tExpString, context)
445+
local res, err = luaxp.run(compiledExpression, context)
442446
if err then
443447
error("evaluation error: " .. err.message)
444448
end

0 commit comments

Comments
 (0)