41
41
import os
42
42
import sys
43
43
import types
44
- from time import time
44
+ from time import time , monotonic_ns
45
45
46
+ GRAALPYTHON = sys .implementation .name == "graalpython"
46
47
47
48
_HRULE = '-' .join (['' for i in range (80 )])
48
49
@@ -195,7 +196,7 @@ def _as_int(value):
195
196
196
197
197
198
class BenchRunner (object ):
198
- def __init__ (self , bench_file , bench_args = None , iterations = 1 , warmup = - 1 , warmup_runs = 0 ):
199
+ def __init__ (self , bench_file , bench_args = None , iterations = 1 , warmup = - 1 , warmup_runs = 0 , startup = False ):
199
200
assert isinstance (iterations , int ), \
200
201
"BenchRunner iterations argument must be an int, got %s instead" % iterations
201
202
assert isinstance (warmup , int ), \
@@ -213,6 +214,7 @@ def __init__(self, bench_file, bench_args=None, iterations=1, warmup=-1, warmup_
213
214
self .iterations = 1 if self ._run_once else _iterations
214
215
self .warmup_runs = warmup_runs if warmup_runs > 0 else 0
215
216
self .warmup = warmup if warmup > 0 else - 1
217
+ self .startup = startup
216
218
217
219
@staticmethod
218
220
def get_bench_module (bench_file ):
@@ -271,19 +273,28 @@ def run(self):
271
273
self ._call_attr (ATTR_SETUP , * args )
272
274
print ("### start benchmark ... " )
273
275
276
+ report_startup = GRAALPYTHON and self .startup and __graalpython__ .startup_nano != - 1
277
+
274
278
bench_func = self ._get_attr (ATTR_BENCHMARK )
279
+ startup = - 1
275
280
durations = []
276
281
if bench_func and hasattr (bench_func , '__call__' ):
277
282
if self .warmup_runs :
278
283
print ("### (pre)warming up for %s iterations ... " % self .warmup_runs )
279
284
for _ in range (self .warmup_runs ):
280
285
bench_func (* args )
286
+ cur_time_nano = monotonic_ns ()
287
+ if report_startup and startup == - 1 :
288
+ startup = cur_time_nano - __graalpython__ .startup_nano
281
289
self ._call_attr (ATTR_CLEANUP , * args )
282
290
283
291
for iteration in range (self .iterations ):
284
292
start = time ()
285
293
bench_func (* args )
294
+ cur_time_nano = monotonic_ns ()
286
295
duration = time () - start
296
+ if report_startup and startup == - 1 :
297
+ startup = cur_time_nano - __graalpython__ .startup_nano
287
298
durations .append (duration )
288
299
duration_str = "%.3f" % duration
289
300
self ._call_attr (ATTR_CLEANUP , * args )
@@ -311,6 +322,9 @@ def run(self):
311
322
print (_HRULE )
312
323
313
324
# summary
325
+ # We can do that only on Graalpython
326
+ if report_startup :
327
+ print ("### STARTUP duration: %.3f s" % (startup / 10e9 ))
314
328
if self ._run_once :
315
329
print ("### SINGLE RUN duration: %.3f s" % durations [0 ])
316
330
else :
@@ -333,6 +347,9 @@ def run(self):
333
347
else :
334
348
print ("### WARMUP iteration not specified or could not be detected" )
335
349
350
+ if GRAALPYTHON and self .startup and __graalpython__ .startup_nano == - 1 :
351
+ print ("### Startup could not be measured. You need to enable startup time snapshotting." )
352
+
336
353
print (_HRULE )
337
354
print ("### RAW DURATIONS: %s" % str (durations ))
338
355
print (_HRULE )
@@ -342,6 +359,7 @@ def run_benchmark(args):
342
359
warmup = - 1
343
360
warmup_runs = 0
344
361
iterations = 1
362
+ startup = False
345
363
bench_file = None
346
364
bench_args = []
347
365
paths = []
@@ -367,6 +385,9 @@ def run_benchmark(args):
367
385
elif arg .startswith ("--warmup-runs" ):
368
386
warmup_runs = _as_int (arg .split ("=" )[1 ])
369
387
388
+ elif arg == '-s' or arg == '--startup' :
389
+ startup = True
390
+
370
391
elif arg == '-p' :
371
392
i += 1
372
393
paths = args [i ].split ("," )
@@ -389,7 +410,7 @@ def run_benchmark(args):
389
410
else :
390
411
print ("### no extra module search paths specified" )
391
412
392
- BenchRunner (bench_file , bench_args = bench_args , iterations = iterations , warmup = warmup , warmup_runs = warmup_runs ).run ()
413
+ BenchRunner (bench_file , bench_args = bench_args , iterations = iterations , warmup = warmup , warmup_runs = warmup_runs , startup = startup ).run ()
393
414
394
415
395
416
if __name__ == '__main__' :
0 commit comments