Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add p50 and p95 of memory/CPU usage to benchmark summary script. #332

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 80 additions & 16 deletions scripts/performance/summarize
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ And that should output::
+------------------------+----------+----------------------+


The script can also be ran with multiple files:
The script can also be run with multiple files:

./summarize performance.csv performance-2.csv

Expand Down Expand Up @@ -67,6 +67,7 @@ summary as JSON instead of a pretty printed table::
import argparse
import csv
import json
import math
from math import sqrt

from tabulate import tabulate
Expand Down Expand Up @@ -103,11 +104,19 @@ class Summarizer:
'average_cpu': [],
'max_memory': [],
'max_cpu': [],
'memory_p50': [],
'memory_p95': [],
'cpu_p50': [],
'cpu_p95': [],
}
self._averages = {
'memory': 0.0,
'cpu': 0.0,
}
self._samples = {
'memory': [],
'cpu': [],
}
self._maximums = {'memory': 0.0, 'cpu': 0.0}

@property
Expand All @@ -122,6 +131,22 @@ class Summarizer:
def max_memory(self):
return self._average_across_all_files('max_memory')

@property
def p50_memory(self):
return self._average_across_all_files('memory_p50')

@property
def p50_cpu(self):
return self._average_across_all_files('cpu_p50')

@property
def p95_memory(self):
return self._average_across_all_files('memory_p95')

@property
def p95_cpu(self):
return self._average_across_all_files('cpu_p95')

@property
def average_cpu(self):
return self._average_across_all_files('average_cpu')
Expand All @@ -142,6 +167,22 @@ class Summarizer:
def std_dev_max_memory(self):
return self._standard_deviation_across_all_files('max_memory')

@property
def std_dev_p50_memory(self):
return self._standard_deviation_across_all_files('memory_p50')

@property
def std_dev_p50_cpu(self):
return self._standard_deviation_across_all_files('cpu_p50')

@property
def std_dev_p95_memory(self):
return self._standard_deviation_across_all_files('memory_p95')

@property
def std_dev_p95_cpu(self):
return self._standard_deviation_across_all_files('cpu_p95')

@property
def std_dev_average_cpu(self):
return self._standard_deviation_across_all_files('average_cpu')
Expand Down Expand Up @@ -177,6 +218,10 @@ class Summarizer:
f'{self.max_cpu:.1f}',
self.std_dev_max_cpu,
],
['p95 Memory', h(self.p95_memory), h(self.std_dev_p95_memory)],
['p95 CPU (percent)', f'{self.p95_cpu:.1f}', self.std_dev_p95_cpu],
['p50 Memory', h(self.p50_memory), h(self.std_dev_p50_memory)],
['p50 CPU (percent)', f'{self.p50_cpu:.1f}', self.std_dev_p50_cpu],
[
'Average Memory',
h(self.average_memory),
Expand All @@ -203,21 +248,26 @@ class Summarizer:

:return: str of formatted JSON
"""
return json.dumps(
{
'total_time': self.total_time,
'std_dev_total_time': self.std_dev_total_time,
'max_memory': self.max_memory,
'std_dev_max_memory': self.std_dev_max_memory,
'average_memory': self.average_memory,
'std_dev_average_memory': self.std_dev_average_memory,
'std_dev_max_cpu': self.std_dev_max_cpu,
'max_cpu': self.max_cpu,
'average_cpu': self.average_cpu,
'std_dev_average_cpu': self.std_dev_average_cpu,
},
indent=2,
)
return json.dumps({
'total_time': self.total_time,
'std_dev_total_time': self.std_dev_total_time,
'max_memory': self.max_memory,
'std_dev_max_memory': self.std_dev_max_memory,
'p95_memory': self.p95_memory,
'std_dev_p95_memory': self.std_dev_p95_memory,
'p50_memory': self.p50_memory,
'std_dev_p50_memory': self.std_dev_p50_memory,
'average_memory': self.average_memory,
'std_dev_average_memory': self.std_dev_average_memory,
'std_dev_max_cpu': self.std_dev_max_cpu,
'max_cpu': self.max_cpu,
'p95_cpu': self.p95_cpu,
'std_dev_p95_cpu': self.std_dev_p95_cpu,
'p50_cpu': self.p50_cpu,
'std_dev_p50_cpu': self.std_dev_p50_cpu,
'average_cpu': self.average_cpu,
'std_dev_average_cpu': self.std_dev_average_cpu,
}, indent=2)

def process(self, args):
"""Processes the data from the CSV file"""
Expand Down Expand Up @@ -259,6 +309,7 @@ class Summarizer:
data_point = float(row[index])
self._add_to_average(name, data_point)
self._account_for_maximum(name, data_point)
self._samples[name].append(data_point)

def _finalize_processed_data_for_file(self):
# Add numbers to the total, which keeps track of data over
Expand All @@ -272,12 +323,25 @@ class Summarizer:
self._totals['average_memory'].append(
self._averages['memory'] / self._num_rows
)
self._samples['memory'].sort()
self._samples['cpu'].sort()
self._totals['memory_p50'].append(self._compute_metric_percentile(50, 'memory'))
self._totals['memory_p95'].append(self._compute_metric_percentile(95, 'memory'))
self._totals['cpu_p50'].append(self._compute_metric_percentile(50, 'cpu'))
self._totals['cpu_p95'].append(self._compute_metric_percentile(95, 'cpu'))

# Reset some of the data needed to be tracked for each specific
# file.
self._num_rows = 0
self._maximums = self._maximums.fromkeys(self._maximums, 0.0)
self._averages = self._averages.fromkeys(self._averages, 0.0)
self._samples['memory'].clear()
self._samples['cpu'].clear()

def _compute_metric_percentile(self, percentile, name):
num_samples = len(self._samples[name])
p_idx = math.ceil(percentile*num_samples/100) - 1
return self._samples[name][p_idx]

def _get_time(self, row):
return float(row[self.DATA_INDEX_IN_ROW['time']])
Expand Down
Loading