1111import os
1212import json
1313import 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
2219from jmespath .parser import Parser
2320from 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
3031def 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
4955def _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
6271def _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
7688def _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
90106def _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
107127def load_tests (filename ):
@@ -118,28 +138,23 @@ def load_tests(filename):
118138
119139def _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
130152def 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
0 commit comments