11
11
import os
12
12
import json
13
13
import sys
14
+ import timeit
14
15
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
20
17
21
18
22
19
from jmespath .parser import Parser
23
20
from jmespath .lexer import Lexer
24
21
25
22
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
28
29
29
30
30
31
def run_tests (tests ):
@@ -33,64 +34,82 @@ def run_tests(tests):
33
34
given = test ['given' ]
34
35
expression = test ['expression' ]
35
36
result = test ['result' ]
37
+ should_search = test ['bench_type' ] == 'full'
36
38
lex_time = _lex_time (expression )
37
39
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
40
46
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 ))
46
52
sys .stdout .write ("name: %s\n " % test ['name' ])
47
53
48
54
49
55
def _lex_time (expression , clock = _clock ):
50
- best = float ('inf' )
51
56
lex = Lexer ()
52
- for i in range (DEFAULT_NUM_LOOP ):
57
+ duration = 0
58
+ i = 0
59
+ while True :
60
+ i += 1
53
61
start = clock ()
54
62
list (lex .tokenize (expression ))
55
63
end = clock ()
56
64
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
60
69
61
70
62
71
def _search_time (expression , given , clock = _clock ):
63
72
p = Parser ()
64
73
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
67
78
start = clock ()
68
79
parsed .search (given )
69
80
end = clock ()
70
81
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
74
86
75
87
76
88
def _parse_time (expression , clock = _clock ):
77
89
best = float ('inf' )
78
90
p = Parser ()
79
- for i in range (DEFAULT_NUM_LOOP ):
91
+ duration = 0
92
+ i = 0
93
+ while True :
94
+ i += 1
80
95
p .purge ()
81
96
start = clock ()
82
97
p .parse (expression )
83
98
end = clock ()
84
99
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
88
104
89
105
90
106
def _combined_time (expression , given , result , clock = _clock ):
91
107
best = float ('inf' )
92
108
p = Parser ()
93
- for i in range (DEFAULT_NUM_LOOP ):
109
+ duration = 0
110
+ i = 0
111
+ while True :
112
+ i += 1
94
113
p .purge ()
95
114
start = clock ()
96
115
r = p .parse (expression ).search (given )
@@ -99,9 +118,10 @@ def _combined_time(expression, given, result, clock=_clock):
99
118
if r != result :
100
119
raise RuntimeError ("Unexpected result, received: %s, "
101
120
"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
105
125
106
126
107
127
def load_tests (filename ):
@@ -118,28 +138,23 @@ def load_tests(filename):
118
138
119
139
def _add_cases (data , loaded , filename ):
120
140
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
+ }
126
148
loaded .append (current )
127
149
return loaded
128
150
129
151
130
152
def main ():
131
153
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 )
134
155
args = parser .parse_args ()
135
156
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 ))
143
158
run_tests (collected_tests )
144
159
145
160
0 commit comments