Skip to content

Commit 4eaa65b

Browse files
committed
Merge branch 'bench-compliance' into develop
* bench-compliance: Use benchmarks.json file for benchmarking Change perf test to be time based
2 parents 14cdfb8 + 072fb51 commit 4eaa65b

File tree

2 files changed

+91
-52
lines changed

2 files changed

+91
-52
lines changed

perf/perftest.py

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@
1111
import os
1212
import json
1313
import sys
14+
import timeit
1415

15-
try:
16-
_clock = time.process_time
17-
except AttributeError:
18-
# Python 2.x does not have time.process_time
19-
_clock = time.clock
16+
_clock = timeit.default_timer
2017

2118

2219
from jmespath.parser import Parser
2320
from jmespath.lexer import Lexer
2421

2522

26-
DIRECTORY = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cases')
27-
DEFAULT_NUM_LOOP = 100
23+
BENCHMARK_FILE = os.path.join(
24+
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
25+
'tests',
26+
'compliance',
27+
'benchmarks.json')
28+
APPROX_RUN_TIME = 0.5
2829

2930

3031
def run_tests(tests):
@@ -33,64 +34,82 @@ def run_tests(tests):
3334
given = test['given']
3435
expression = test['expression']
3536
result = test['result']
37+
should_search = test['bench_type'] == 'full'
3638
lex_time = _lex_time(expression)
3739
parse_time = _parse_time(expression)
38-
search_time = _search_time(expression, given)
39-
combined_time = _combined_time(expression, given, result)
40+
if should_search:
41+
search_time = _search_time(expression, given)
42+
combined_time = _combined_time(expression, given, result)
43+
else:
44+
search_time = 0
45+
combined_time = 0
4046
sys.stdout.write(
41-
"lex_time: %.5fms, parse_time: %.5fms, search_time: %.5fms "
42-
"combined_time: %.5fms " % (1000 * lex_time,
43-
1000 * parse_time,
44-
1000 * search_time,
45-
1000 * combined_time))
47+
"lex_time: %10.5fus, parse_time: %10.5fus, search_time: %10.5fus "
48+
"combined_time: %10.5fus " % (1000000 * lex_time,
49+
1000000 * parse_time,
50+
1000000 * search_time,
51+
1000000 * combined_time))
4652
sys.stdout.write("name: %s\n" % test['name'])
4753

4854

4955
def _lex_time(expression, clock=_clock):
50-
best = float('inf')
5156
lex = Lexer()
52-
for i in range(DEFAULT_NUM_LOOP):
57+
duration = 0
58+
i = 0
59+
while True:
60+
i += 1
5361
start = clock()
5462
list(lex.tokenize(expression))
5563
end = clock()
5664
total = end - start
57-
if total < best:
58-
best = total
59-
return best
65+
duration += total
66+
if duration >= APPROX_RUN_TIME:
67+
break
68+
return duration / i
6069

6170

6271
def _search_time(expression, given, clock=_clock):
6372
p = Parser()
6473
parsed = p.parse(expression)
65-
best = float('inf')
66-
for i in range(DEFAULT_NUM_LOOP):
74+
duration = 0
75+
i = 0
76+
while True:
77+
i += 1
6778
start = clock()
6879
parsed.search(given)
6980
end = clock()
7081
total = end - start
71-
if total < best:
72-
best = total
73-
return best
82+
duration += total
83+
if duration >= APPROX_RUN_TIME:
84+
break
85+
return duration / i
7486

7587

7688
def _parse_time(expression, clock=_clock):
7789
best = float('inf')
7890
p = Parser()
79-
for i in range(DEFAULT_NUM_LOOP):
91+
duration = 0
92+
i = 0
93+
while True:
94+
i += 1
8095
p.purge()
8196
start = clock()
8297
p.parse(expression)
8398
end = clock()
8499
total = end - start
85-
if total < best:
86-
best = total
87-
return best
100+
duration += total
101+
if duration >= APPROX_RUN_TIME:
102+
break
103+
return duration / i
88104

89105

90106
def _combined_time(expression, given, result, clock=_clock):
91107
best = float('inf')
92108
p = Parser()
93-
for i in range(DEFAULT_NUM_LOOP):
109+
duration = 0
110+
i = 0
111+
while True:
112+
i += 1
94113
p.purge()
95114
start = clock()
96115
r = p.parse(expression).search(given)
@@ -99,9 +118,10 @@ def _combined_time(expression, given, result, clock=_clock):
99118
if r != result:
100119
raise RuntimeError("Unexpected result, received: %s, "
101120
"expected: %s" % (r, result))
102-
if total < best:
103-
best = total
104-
return best
121+
duration += total
122+
if duration >= APPROX_RUN_TIME:
123+
break
124+
return duration / i
105125

106126

107127
def load_tests(filename):
@@ -118,28 +138,23 @@ def load_tests(filename):
118138

119139
def _add_cases(data, loaded, filename):
120140
for case in data['cases']:
121-
current = {'description': data.get('description', filename),
122-
'given': data['given'],
123-
'name': case.get('name', case['expression']),
124-
'expression': case['expression'],
125-
'result': case.get('result')}
141+
current = {
142+
'given': data['given'],
143+
'name': case.get('comment', case['expression']),
144+
'expression': case['expression'],
145+
'result': case.get('result'),
146+
'bench_type': case['bench'],
147+
}
126148
loaded.append(current)
127149
return loaded
128150

129151

130152
def main():
131153
parser = argparse.ArgumentParser()
132-
parser.add_argument('-d', '--directory', default=DIRECTORY)
133-
parser.add_argument('-f', '--filename')
154+
parser.add_argument('-f', '--filename', default=BENCHMARK_FILE)
134155
args = parser.parse_args()
135156
collected_tests = []
136-
if args.filename:
137-
collected_tests.extend(load_tests(args.filename))
138-
else:
139-
for filename in os.listdir(args.directory):
140-
if filename.endswith('.json'):
141-
full_path = os.path.join(args.directory, filename)
142-
collected_tests.extend(load_tests(full_path))
157+
collected_tests.extend(load_tests(args.filename))
143158
run_tests(collected_tests)
144159

145160

tests/compliance/benchmarks.json

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,41 @@
3232
}
3333
}
3434
}
35+
},
36+
"b": true,
37+
"c": {
38+
"d": true
3539
}
3640
},
3741
"cases": [
3842
{
3943
"comment": "simple field",
40-
"expression": "a",
44+
"expression": "b",
45+
"result": true,
4146
"bench": "full"
4247
},
4348
{
4449
"comment": "simple subexpression",
45-
"expression": "a.b",
50+
"expression": "c.d",
51+
"result": true,
4652
"bench": "full"
4753
},
4854
{
49-
"comment": "deep field selection",
55+
"comment": "deep field selection no match",
5056
"expression": "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s",
57+
"result": null,
58+
"bench": "full"
59+
},
60+
{
61+
"comment": "deep field selection",
62+
"expression": "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p",
63+
"result": true,
5164
"bench": "full"
5265
},
5366
{
5467
"comment": "simple or",
55-
"expression": "not_there || a",
68+
"expression": "not_there || b",
69+
"result": true,
5670
"bench": "full"
5771
}
5872
]
@@ -67,21 +81,31 @@
6781
{
6882
"comment": "deep ands",
6983
"expression": "a && b && c && d && e && f && g && h && i && j && k && l && m && n && o && p && q && r && s && t && u && v && w && x && y && z",
84+
"result": 25,
7085
"bench": "full"
7186
},
7287
{
7388
"comment": "deep ors",
7489
"expression": "z || y || x || w || v || u || t || s || r || q || p || o || n || m || l || k || j || i || h || g || f || e || d || c || b || a",
90+
"result": 25,
7591
"bench": "full"
7692
},
7793
{
7894
"comment": "lots of summing",
79-
"expression": "sum(z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a)",
95+
"expression": "sum([z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a])",
96+
"result": 325,
97+
"bench": "full"
98+
},
99+
{
100+
"comment": "lots of function application",
101+
"expression": "sum([z, sum([y, sum([x, sum([w, sum([v, sum([u, sum([t, sum([s, sum([r, sum([q, sum([p, sum([o, sum([n, sum([m, sum([l, sum([k, sum([j, sum([i, sum([h, sum([g, sum([f, sum([e, sum([d, sum([c, sum([b, a])])])])])])])])])])])])])])])])])])])])])])])])])",
102+
"result": 325,
80103
"bench": "full"
81104
},
82105
{
83106
"comment": "lots of multi list",
84107
"expression": "[z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a]",
108+
"result": [25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
85109
"bench": "full"
86110
}
87111
]
@@ -116,7 +140,7 @@
116140
},
117141
{
118142
"comment": "filter projection",
119-
"expression": "foo[bar > baz][qux > baz]",
143+
"expression": "foo[?bar > baz][?qux > baz]",
120144
"bench": "parse"
121145
}
122146
]

0 commit comments

Comments
 (0)