Skip to content

Commit cc0e16c

Browse files
committed
[benchmark] LogParser: measurement metadata
1 parent 5571b83 commit cc0e16c

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

benchmark/scripts/compare_perf_tests.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ class PerformanceTestResult(object):
229229
`--quantile`parameter. In both cases, the last column, MAX_RSS is optional.
230230
"""
231231

232-
def __init__(self, csv_row, quantiles=False, memory=False, delta=False):
232+
def __init__(self, csv_row, quantiles=False, memory=False, delta=False,
233+
meta=False):
233234
"""Initialize from a row of multiple columns with benchmark summary.
234235
235236
The row is an iterable, such as a row provided by the CSV parser.
@@ -239,7 +240,8 @@ def __init__(self, csv_row, quantiles=False, memory=False, delta=False):
239240
self.num_samples = int(csv_row[2]) # Number of measurements taken
240241

241242
if quantiles: # Variable number of columns representing quantiles
242-
runtimes = csv_row[3:-1] if memory else csv_row[3:]
243+
mem_index = (-1 if memory else 0) + (-3 if meta else 0)
244+
runtimes = csv_row[3:mem_index] if memory or meta else csv_row[3:]
243245
if delta:
244246
runtimes = [int(x) if x else 0 for x in runtimes]
245247
runtimes = reduce(lambda l, x: l.append(l[-1] + x) or # runnin
@@ -261,7 +263,7 @@ def __init__(self, csv_row, quantiles=False, memory=False, delta=False):
261263
self.min, self.max, self.median, self.mean, self.sd = \
262264
sams.min, sams.max, sams.median, sams.mean, sams.sd
263265
self.max_rss = ( # Maximum Resident Set Size (B)
264-
int(csv_row[-1]) if memory else None)
266+
int(csv_row[mem_index]) if memory else None)
265267
else: # Legacy format with statistics for normal distribution.
266268
self.min = int(csv_row[3]) # Minimum runtime (μs)
267269
self.max = int(csv_row[4]) # Maximum runtime (μs)
@@ -271,6 +273,11 @@ def __init__(self, csv_row, quantiles=False, memory=False, delta=False):
271273
self.max_rss = ( # Maximum Resident Set Size (B)
272274
int(csv_row[8]) if len(csv_row) > 8 else None)
273275
self.samples = None
276+
277+
# Optional measurement metadata. The number of:
278+
# memory pages used, involuntary context switches and voluntary yields
279+
self.mem_pages, self.involuntary_cs, self.yield_count = \
280+
[int(x) for x in csv_row[-3:]] if meta else (None, None, None)
274281
self.yields = None
275282
self.setup = None
276283

@@ -352,6 +359,7 @@ def __init__(self):
352359
"""Create instance of `LogParser`."""
353360
self.results = []
354361
self.quantiles, self.delta, self.memory = False, False, False
362+
self.meta = False
355363
self._reset()
356364

357365
def _reset(self):
@@ -371,12 +379,12 @@ def _append_result(self, result):
371379
columns = result.split(',') if ',' in result else result.split()
372380
r = PerformanceTestResult(
373381
columns, quantiles=self.quantiles, memory=self.memory,
374-
delta=self.delta)
382+
delta=self.delta, meta=self.meta)
375383
r.setup = self.setup
376384
r.max_rss = r.max_rss or self.max_rss
377-
r.mem_pages = self.mem_pages
385+
r.mem_pages = r.mem_pages or self.mem_pages
378386
r.voluntary_cs = self.voluntary_cs
379-
r.involuntary_cs = self.involuntary_cs
387+
r.involuntary_cs = r.involuntary_cs or self.involuntary_cs
380388
if self.samples:
381389
r.samples = PerformanceTestSamples(r.name, self.samples)
382390
r.samples.exclude_outliers()
@@ -391,6 +399,7 @@ def _store_memory_stats(self, max_rss, mem_pages):
391399
def _configure_format(self, header):
392400
self.quantiles = 'MEAN' not in header
393401
self.memory = 'MAX_RSS' in header
402+
self.meta = 'PAGES' in header
394403
self.delta = '𝚫' in header
395404

396405
# Regular expression and action to take when it matches the parsed line

benchmark/scripts/test_compare_perf_tests.py

+67
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,46 @@ def validatePTR(deq): # construct from delta encoded quantiles string
308308
1,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"""
309309
map(validatePTR, delta_encoded_quantiles.split('\n')[1:])
310310

311+
def test_init_meta(self):
312+
# #,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs),…
313+
# …PAGES,ICS,YIELD
314+
log = '1,Ackermann,200,715,1281,726,47,715,7,29,15'
315+
r = PerformanceTestResult(log.split(','), meta=True)
316+
self.assertEqual((r.test_num, r.name), ('1', 'Ackermann'))
317+
self.assertEqual(
318+
(r.num_samples, r.min, r.max, r.mean, r.sd, r.median),
319+
(200, 715, 1281, 726, 47, 715))
320+
self.assertEqual((r.mem_pages, r.involuntary_cs, r.yield_count),
321+
(7, 29, 15))
322+
# #,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs),MAX_RSS(B),…
323+
# …PAGES,ICS,YIELD
324+
log = '1,Ackermann,200,715,1951,734,97,715,36864,9,50,15'
325+
r = PerformanceTestResult(log.split(','), memory=True, meta=True)
326+
self.assertEqual(
327+
(r.num_samples, r.min, r.max, r.mean, r.sd, r.median),
328+
(200, 715, 1951, 734, 97, 715))
329+
self.assertEqual(
330+
(r.mem_pages, r.involuntary_cs, r.yield_count, r.max_rss),
331+
(9, 50, 15, 36864))
332+
# #,TEST,SAMPLES,MIN(μs),MAX(μs),PAGES,ICS,YIELD
333+
log = '1,Ackermann,200,715,3548,8,31,15'
334+
r = PerformanceTestResult(log.split(','), quantiles=True, meta=True)
335+
self.assertEqual((r.num_samples, r.min, r.max), (200, 715, 3548))
336+
self.assertEqual((r.samples.count, r.samples.min, r.samples.max),
337+
(2, 715, 3548))
338+
self.assertEqual((r.mem_pages, r.involuntary_cs, r.yield_count),
339+
(8, 31, 15))
340+
# #,TEST,SAMPLES,MIN(μs),MAX(μs),MAX_RSS(B),PAGES,ICS,YIELD
341+
log = '1,Ackermann,200,715,1259,32768,8,28,15'
342+
r = PerformanceTestResult(
343+
log.split(','), quantiles=True, memory=True, meta=True)
344+
self.assertEqual((r.num_samples, r.min, r.max), (200, 715, 1259))
345+
self.assertEqual((r.samples.count, r.samples.min, r.samples.max),
346+
(2, 715, 1259))
347+
self.assertEquals(r.max_rss, 32768)
348+
self.assertEqual((r.mem_pages, r.involuntary_cs, r.yield_count),
349+
(8, 28, 15))
350+
311351
def test_repr(self):
312352
log_line = '1,AngryPhonebook,20,10664,12933,11035,576,10884'
313353
r = PerformanceTestResult(log_line.split(','))
@@ -517,6 +557,33 @@ def test_parse_delta_quantiles(self):
517557
# last 3 ventiles were outliers and were excluded from the sample
518558
(200, 214, 215, 18))
519559

560+
def test_parse_meta(self):
561+
r = LogParser.results_from_string(
562+
'#,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs),' +
563+
'PAGES,ICS,YIELD\n' +
564+
'0,B,1,2,2,2,0,2,7,29,15')['B']
565+
self.assertEqual(
566+
(r.min, r.mem_pages, r.involuntary_cs, r.yield_count),
567+
(2, 7, 29, 15))
568+
r = LogParser.results_from_string(
569+
'#,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs),' +
570+
'MAX_RSS(B),PAGES,ICS,YIELD\n' +
571+
'0,B,1,3,3,3,0,3,36864,9,50,15')['B']
572+
self.assertEqual(
573+
(r.min, r.mem_pages, r.involuntary_cs, r.yield_count, r.max_rss),
574+
(3, 9, 50, 15, 36864))
575+
r = LogParser.results_from_string(
576+
'#,TEST,SAMPLES,MIN(μs),MAX(μs),PAGES,ICS,YIELD\n' +
577+
'0,B,1,4,4,8,31,15')['B']
578+
self.assertEqual((r.min, r.mem_pages, r.involuntary_cs, r.yield_count),
579+
(4, 8, 31, 15))
580+
r = LogParser.results_from_string(
581+
'#,TEST,SAMPLES,MIN(μs),MAX(μs),MAX_RSS(B),PAGES,ICS,YIELD\n' +
582+
'0,B,1,5,5,32768,8,28,15')['B']
583+
self.assertEqual(
584+
(r.min, r.mem_pages, r.involuntary_cs, r.yield_count, r.max_rss),
585+
(5, 8, 28, 15, 32768))
586+
520587
def test_parse_results_verbose(self):
521588
"""Parse multiple performance test results with 2 sample formats:
522589
single line for N = 1; two lines for N > 1.

0 commit comments

Comments
 (0)