summaryrefslogtreecommitdiffstats
path: root/import-layers/yocto-poky/scripts/lib/build_perf
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/scripts/lib/build_perf')
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/__init__.py31
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/html.py19
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/html/measurement_chart.html50
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/html/report.html286
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/report.py345
-rw-r--r--import-layers/yocto-poky/scripts/lib/build_perf/scrape-html-report.js56
6 files changed, 0 insertions, 787 deletions
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/__init__.py b/import-layers/yocto-poky/scripts/lib/build_perf/__init__.py
deleted file mode 100644
index 1f8b72907..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (c) 2017, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-"""Build performance test library functions"""
-
-def print_table(rows, row_fmt=None):
- """Print data table"""
- if not rows:
- return
- if not row_fmt:
- row_fmt = ['{:{wid}} '] * len(rows[0])
-
- # Go through the data to get maximum cell widths
- num_cols = len(row_fmt)
- col_widths = [0] * num_cols
- for row in rows:
- for i, val in enumerate(row):
- col_widths[i] = max(col_widths[i], len(str(val)))
-
- for row in rows:
- print(*[row_fmt[i].format(col, wid=col_widths[i]) for i, col in enumerate(row)])
-
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/html.py b/import-layers/yocto-poky/scripts/lib/build_perf/html.py
deleted file mode 100644
index 578bb162e..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/html.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (c) 2017, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-"""Helper module for HTML reporting"""
-from jinja2 import Environment, PackageLoader
-
-
-env = Environment(loader=PackageLoader('build_perf', 'html'))
-
-template = env.get_template('report.html')
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/html/measurement_chart.html b/import-layers/yocto-poky/scripts/lib/build_perf/html/measurement_chart.html
deleted file mode 100644
index 65f1a227a..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/html/measurement_chart.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<script type="text/javascript">
- chartsDrawing += 1;
- google.charts.setOnLoadCallback(drawChart_{{ chart_elem_id }});
- function drawChart_{{ chart_elem_id }}() {
- var data = new google.visualization.DataTable();
-
- // Chart options
- var options = {
- theme : 'material',
- legend: 'none',
- hAxis: { format: '', title: 'Commit number',
- minValue: {{ chart_opts.haxis.min }},
- maxValue: {{ chart_opts.haxis.max }} },
- {% if measurement.type == 'time' %}
- vAxis: { format: 'h:mm:ss' },
- {% else %}
- vAxis: { format: '' },
- {% endif %}
- pointSize: 5,
- chartArea: { left: 80, right: 15 },
- };
-
- // Define data columns
- data.addColumn('number', 'Commit');
- data.addColumn('{{ measurement.value_type.gv_data_type }}',
- '{{ measurement.value_type.quantity }}');
- // Add data rows
- data.addRows([
- {% for sample in measurement.samples %}
- [{{ sample.commit_num }}, {{ sample.mean.gv_value() }}],
- {% endfor %}
- ]);
-
- // Finally, draw the chart
- chart_div = document.getElementById('{{ chart_elem_id }}');
- var chart = new google.visualization.LineChart(chart_div);
- google.visualization.events.addListener(chart, 'ready', function () {
- //chart_div = document.getElementById('{{ chart_elem_id }}');
- //chart_div.innerHTML = '<img src="' + chart.getImageURI() + '">';
- png_div = document.getElementById('{{ chart_elem_id }}_png');
- png_div.outerHTML = '<a id="{{ chart_elem_id }}_png" href="' + chart.getImageURI() + '">PNG</a>';
- console.log("CHART READY: {{ chart_elem_id }}");
- chartsDrawing -= 1;
- if (chartsDrawing == 0)
- console.log("ALL CHARTS READY");
- });
- chart.draw(data, options);
-}
-</script>
-
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/html/report.html b/import-layers/yocto-poky/scripts/lib/build_perf/html/report.html
deleted file mode 100644
index 291ad9d72..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/html/report.html
+++ /dev/null
@@ -1,286 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-{# Scripts, for visualization#}
-<!--START-OF-SCRIPTS-->
-<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
-<script type="text/javascript">
-google.charts.load('current', {'packages':['corechart']});
-var chartsDrawing = 0;
-</script>
-
-{# Render measurement result charts #}
-{% for test in test_data %}
- {% if test.status == 'SUCCESS' %}
- {% for measurement in test.measurements %}
- {% set chart_elem_id = test.name + '_' + measurement.name + '_chart' %}
- {% include 'measurement_chart.html' %}
- {% endfor %}
- {% endif %}
-{% endfor %}
-
-<!--END-OF-SCRIPTS-->
-
-{# Styles #}
-<style>
-.meta-table {
- font-size: 14px;
- text-align: left;
- border-collapse: collapse;
-}
-.meta-table tr:nth-child(even){background-color: #f2f2f2}
-meta-table th, .meta-table td {
- padding: 4px;
-}
-.summary {
- margin: 0;
- font-size: 14px;
- text-align: left;
- border-collapse: collapse;
-}
-summary th, .meta-table td {
- padding: 4px;
-}
-.measurement {
- padding: 8px 0px 8px 8px;
- border: 2px solid #f0f0f0;
- margin-bottom: 10px;
-}
-.details {
- margin: 0;
- font-size: 12px;
- text-align: left;
- border-collapse: collapse;
-}
-.details th {
- padding-right: 8px;
-}
-.details.plain th {
- font-weight: normal;
-}
-.preformatted {
- font-family: monospace;
- white-space: pre-wrap;
- background-color: #f0f0f0;
- margin-left: 10px;
-}
-hr {
- color: #f0f0f0;
-}
-h2 {
- font-size: 20px;
- margin-bottom: 0px;
- color: #707070;
-}
-h3 {
- font-size: 16px;
- margin: 0px;
- color: #707070;
-}
-</style>
-
-<title>{{ title }}</title>
-</head>
-
-{% macro poky_link(commit) -%}
- <a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?id={{ commit }}">{{ commit[0:11] }}</a>
-{%- endmacro %}
-
-<body><div style="width: 700px">
- {# Test metadata #}
- <h2>General</h2>
- <hr>
- <table class="meta-table" style="width: 100%">
- <tr>
- <th></th>
- <th>Current commit</th>
- <th>Comparing with</th>
- </tr>
- {% for key, item in metadata.items() %}
- <tr>
- <th>{{ item.title }}</th>
- {%if key == 'commit' %}
- <td>{{ poky_link(item.value) }}</td>
- <td>{{ poky_link(item.value_old) }}</td>
- {% else %}
- <td>{{ item.value }}</td>
- <td>{{ item.value_old }}</td>
- {% endif %}
- </tr>
- {% endfor %}
- </table>
-
- {# Test result summary #}
- <h2>Test result summary</h2>
- <hr>
- <table class="summary" style="width: 100%">
- {% for test in test_data %}
- {% if loop.index is even %}
- {% set row_style = 'style="background-color: #f2f2f2"' %}
- {% else %}
- {% set row_style = 'style="background-color: #ffffff"' %}
- {% endif %}
- {% if test.status == 'SUCCESS' %}
- {% for measurement in test.measurements %}
- <tr {{ row_style }}>
- {% if loop.index == 1 %}
- <td>{{ test.name }}: {{ test.description }}</td>
- {% else %}
- {# add empty cell in place of the test name#}
- <td></td>
- {% endif %}
- {% if measurement.absdiff > 0 %}
- {% set result_style = "color: red" %}
- {% elif measurement.absdiff == measurement.absdiff %}
- {% set result_style = "color: green" %}
- {% else %}
- {% set result_style = "color: orange" %}
- {%endif %}
- <td>{{ measurement.description }}</td>
- <td style="font-weight: bold">{{ measurement.value.mean }}</td>
- <td style="{{ result_style }}">{{ measurement.absdiff_str }}</td>
- <td style="{{ result_style }}">{{ measurement.reldiff }}</td>
- </tr>
- {% endfor %}
- {% else %}
- <td style="font-weight: bold; color: red;">{{test.status }}</td>
- <td></td> <td></td> <td></td> <td></td>
- {% endif %}
- {% endfor %}
- </table>
-
- {# Detailed test results #}
- {% for test in test_data %}
- <h2>{{ test.name }}: {{ test.description }}</h2>
- <hr>
- {% if test.status == 'SUCCESS' %}
- {% for measurement in test.measurements %}
- <div class="measurement">
- <h3>{{ measurement.description }}</h3>
- <div style="font-weight:bold;">
- <span style="font-size: 23px;">{{ measurement.value.mean }}</span>
- <span style="font-size: 20px; margin-left: 12px">
- {% if measurement.absdiff > 0 %}
- <span style="color: red">
- {% elif measurement.absdiff == measurement.absdiff %}
- <span style="color: green">
- {% else %}
- <span style="color: orange">
- {% endif %}
- {{ measurement.absdiff_str }} ({{measurement.reldiff}})
- </span></span>
- </div>
- {# Table for trendchart and the statistics #}
- <table style="width: 100%">
- <tr>
- <td style="width: 75%">
- {# Linechart #}
- <div id="{{ test.name }}_{{ measurement.name }}_chart"></div>
- </td>
- <td>
- {# Measurement statistics #}
- <table class="details plain">
- <tr>
- <th>Test runs</th><td>{{ measurement.value.sample_cnt }}</td>
- </tr><tr>
- <th>-/+</th><td>-{{ measurement.value.minus }} / +{{ measurement.value.plus }}</td>
- </tr><tr>
- <th>Min</th><td>{{ measurement.value.min }}</td>
- </tr><tr>
- <th>Max</th><td>{{ measurement.value.max }}</td>
- </tr><tr>
- <th>Stdev</th><td>{{ measurement.value.stdev }}</td>
- </tr><tr>
- <th><div id="{{ test.name }}_{{ measurement.name }}_chart_png"></div></th>
- <td></td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
-
- {# Task and recipe summary from buildstats #}
- {% if 'buildstats' in measurement %}
- Task resource usage
- <table class="details" style="width:100%">
- <tr>
- <th>Number of tasks</th>
- <th>Top consumers of cputime</th>
- </tr>
- <tr>
- <td style="vertical-align: top">{{ measurement.buildstats.tasks.count }} ({{ measurement.buildstats.tasks.change }})</td>
- {# Table of most resource-hungry tasks #}
- <td>
- <table class="details plain">
- {% for diff in measurement.buildstats.top_consumer|reverse %}
- <tr>
- <th>{{ diff.pkg }}.{{ diff.task }}</th>
- <td>{{ '%0.0f' % diff.value2 }} s</td>
- </tr>
- {% endfor %}
- </table>
- </td>
- </tr>
- <tr>
- <th>Biggest increase in cputime</th>
- <th>Biggest decrease in cputime</th>
- </tr>
- <tr>
- {# Table biggest increase in resource usage #}
- <td>
- <table class="details plain">
- {% for diff in measurement.buildstats.top_increase|reverse %}
- <tr>
- <th>{{ diff.pkg }}.{{ diff.task }}</th>
- <td>{{ '%+0.0f' % diff.absdiff }} s</td>
- </tr>
- {% endfor %}
- </table>
- </td>
- {# Table biggest decrease in resource usage #}
- <td>
- <table class="details plain">
- {% for diff in measurement.buildstats.top_decrease %}
- <tr>
- <th>{{ diff.pkg }}.{{ diff.task }}</th>
- <td>{{ '%+0.0f' % diff.absdiff }} s</td>
- </tr>
- {% endfor %}
- </table>
- </td>
- </tr>
- </table>
-
- {# Recipe version differences #}
- {% if measurement.buildstats.ver_diff %}
- <div style="margin-top: 16px">Recipe version changes</div>
- <table class="details">
- {% for head, recipes in measurement.buildstats.ver_diff.items() %}
- <tr>
- <th colspan="2">{{ head }}</th>
- </tr>
- {% for name, info in recipes|sort %}
- <tr>
- <td>{{ name }}</td>
- <td>{{ info }}</td>
- </tr>
- {% endfor %}
- {% endfor %}
- </table>
- {% else %}
- <div style="margin-top: 16px">No recipe version changes detected</div>
- {% endif %}
- {% endif %}
- </div>
- {% endfor %}
- {# Unsuccessful test #}
- {% else %}
- <span style="font-size: 150%; font-weight: bold; color: red;">{{ test.status }}
- {% if test.err_type %}<span style="font-size: 75%; font-weight: normal">({{ test.err_type }})</span>{% endif %}
- </span>
- <div class="preformatted">{{ test.message }}</div>
- {% endif %}
- {% endfor %}
-</div></body>
-</html>
-
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/report.py b/import-layers/yocto-poky/scripts/lib/build_perf/report.py
deleted file mode 100644
index d99a36797..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/report.py
+++ /dev/null
@@ -1,345 +0,0 @@
-#
-# Copyright (c) 2017, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-"""Handling of build perf test reports"""
-from collections import OrderedDict, Mapping, namedtuple
-from datetime import datetime, timezone
-from numbers import Number
-from statistics import mean, stdev, variance
-
-
-AggregateTestData = namedtuple('AggregateTestData', ['metadata', 'results'])
-
-
-def isofmt_to_timestamp(string):
- """Convert timestamp string in ISO 8601 format into unix timestamp"""
- if '.' in string:
- dt = datetime.strptime(string, '%Y-%m-%dT%H:%M:%S.%f')
- else:
- dt = datetime.strptime(string, '%Y-%m-%dT%H:%M:%S')
- return dt.replace(tzinfo=timezone.utc).timestamp()
-
-
-def metadata_xml_to_json(elem):
- """Convert metadata xml into JSON format"""
- assert elem.tag == 'metadata', "Invalid metadata file format"
-
- def _xml_to_json(elem):
- """Convert xml element to JSON object"""
- out = OrderedDict()
- for child in elem.getchildren():
- key = child.attrib.get('name', child.tag)
- if len(child):
- out[key] = _xml_to_json(child)
- else:
- out[key] = child.text
- return out
- return _xml_to_json(elem)
-
-
-def results_xml_to_json(elem):
- """Convert results xml into JSON format"""
- rusage_fields = ('ru_utime', 'ru_stime', 'ru_maxrss', 'ru_minflt',
- 'ru_majflt', 'ru_inblock', 'ru_oublock', 'ru_nvcsw',
- 'ru_nivcsw')
- iostat_fields = ('rchar', 'wchar', 'syscr', 'syscw', 'read_bytes',
- 'write_bytes', 'cancelled_write_bytes')
-
- def _read_measurement(elem):
- """Convert measurement to JSON"""
- data = OrderedDict()
- data['type'] = elem.tag
- data['name'] = elem.attrib['name']
- data['legend'] = elem.attrib['legend']
- values = OrderedDict()
-
- # SYSRES measurement
- if elem.tag == 'sysres':
- for subel in elem:
- if subel.tag == 'time':
- values['start_time'] = isofmt_to_timestamp(subel.attrib['timestamp'])
- values['elapsed_time'] = float(subel.text)
- elif subel.tag == 'rusage':
- rusage = OrderedDict()
- for field in rusage_fields:
- if 'time' in field:
- rusage[field] = float(subel.attrib[field])
- else:
- rusage[field] = int(subel.attrib[field])
- values['rusage'] = rusage
- elif subel.tag == 'iostat':
- values['iostat'] = OrderedDict([(f, int(subel.attrib[f]))
- for f in iostat_fields])
- elif subel.tag == 'buildstats_file':
- values['buildstats_file'] = subel.text
- else:
- raise TypeError("Unknown sysres value element '{}'".format(subel.tag))
- # DISKUSAGE measurement
- elif elem.tag == 'diskusage':
- values['size'] = int(elem.find('size').text)
- else:
- raise Exception("Unknown measurement tag '{}'".format(elem.tag))
- data['values'] = values
- return data
-
- def _read_testcase(elem):
- """Convert testcase into JSON"""
- assert elem.tag == 'testcase', "Expecting 'testcase' element instead of {}".format(elem.tag)
-
- data = OrderedDict()
- data['name'] = elem.attrib['name']
- data['description'] = elem.attrib['description']
- data['status'] = 'SUCCESS'
- data['start_time'] = isofmt_to_timestamp(elem.attrib['timestamp'])
- data['elapsed_time'] = float(elem.attrib['time'])
- measurements = OrderedDict()
-
- for subel in elem.getchildren():
- if subel.tag == 'error' or subel.tag == 'failure':
- data['status'] = subel.tag.upper()
- data['message'] = subel.attrib['message']
- data['err_type'] = subel.attrib['type']
- data['err_output'] = subel.text
- elif subel.tag == 'skipped':
- data['status'] = 'SKIPPED'
- data['message'] = subel.text
- else:
- measurements[subel.attrib['name']] = _read_measurement(subel)
- data['measurements'] = measurements
- return data
-
- def _read_testsuite(elem):
- """Convert suite to JSON"""
- assert elem.tag == 'testsuite', \
- "Expecting 'testsuite' element instead of {}".format(elem.tag)
-
- data = OrderedDict()
- if 'hostname' in elem.attrib:
- data['tester_host'] = elem.attrib['hostname']
- data['start_time'] = isofmt_to_timestamp(elem.attrib['timestamp'])
- data['elapsed_time'] = float(elem.attrib['time'])
- tests = OrderedDict()
-
- for case in elem.getchildren():
- tests[case.attrib['name']] = _read_testcase(case)
- data['tests'] = tests
- return data
-
- # Main function
- assert elem.tag == 'testsuites', "Invalid test report format"
- assert len(elem) == 1, "Too many testsuites"
-
- return _read_testsuite(elem.getchildren()[0])
-
-
-def aggregate_metadata(metadata):
- """Aggregate metadata into one, basically a sanity check"""
- mutable_keys = ('pretty_name', 'version_id')
-
- def aggregate_obj(aggregate, obj, assert_str=True):
- """Aggregate objects together"""
- assert type(aggregate) is type(obj), \
- "Type mismatch: {} != {}".format(type(aggregate), type(obj))
- if isinstance(obj, Mapping):
- assert set(aggregate.keys()) == set(obj.keys())
- for key, val in obj.items():
- aggregate_obj(aggregate[key], val, key not in mutable_keys)
- elif isinstance(obj, list):
- assert len(aggregate) == len(obj)
- for i, val in enumerate(obj):
- aggregate_obj(aggregate[i], val)
- elif not isinstance(obj, str) or (isinstance(obj, str) and assert_str):
- assert aggregate == obj, "Data mismatch {} != {}".format(aggregate, obj)
-
- if not metadata:
- return {}
-
- # Do the aggregation
- aggregate = metadata[0].copy()
- for testrun in metadata[1:]:
- aggregate_obj(aggregate, testrun)
- aggregate['testrun_count'] = len(metadata)
- return aggregate
-
-
-def aggregate_data(data):
- """Aggregate multiple test results JSON structures into one"""
-
- mutable_keys = ('status', 'message', 'err_type', 'err_output')
-
- class SampleList(list):
- """Container for numerical samples"""
- pass
-
- def new_aggregate_obj(obj):
- """Create new object for aggregate"""
- if isinstance(obj, Number):
- new_obj = SampleList()
- new_obj.append(obj)
- elif isinstance(obj, str):
- new_obj = obj
- else:
- # Lists and and dicts are kept as is
- new_obj = obj.__class__()
- aggregate_obj(new_obj, obj)
- return new_obj
-
- def aggregate_obj(aggregate, obj, assert_str=True):
- """Recursive "aggregation" of JSON objects"""
- if isinstance(obj, Number):
- assert isinstance(aggregate, SampleList)
- aggregate.append(obj)
- return
-
- assert type(aggregate) == type(obj), \
- "Type mismatch: {} != {}".format(type(aggregate), type(obj))
- if isinstance(obj, Mapping):
- for key, val in obj.items():
- if not key in aggregate:
- aggregate[key] = new_aggregate_obj(val)
- else:
- aggregate_obj(aggregate[key], val, key not in mutable_keys)
- elif isinstance(obj, list):
- for i, val in enumerate(obj):
- if i >= len(aggregate):
- aggregate[key] = new_aggregate_obj(val)
- else:
- aggregate_obj(aggregate[i], val)
- elif isinstance(obj, str):
- # Sanity check for data
- if assert_str:
- assert aggregate == obj, "Data mismatch {} != {}".format(aggregate, obj)
- else:
- raise Exception("BUG: unable to aggregate '{}' ({})".format(type(obj), str(obj)))
-
- if not data:
- return {}
-
- # Do the aggregation
- aggregate = data[0].__class__()
- for testrun in data:
- aggregate_obj(aggregate, testrun)
- return aggregate
-
-
-class MeasurementVal(float):
- """Base class representing measurement values"""
- gv_data_type = 'number'
-
- def gv_value(self):
- """Value formatting for visualization"""
- if self != self:
- return "null"
- else:
- return self
-
-
-class TimeVal(MeasurementVal):
- """Class representing time values"""
- quantity = 'time'
- gv_title = 'elapsed time'
- gv_data_type = 'timeofday'
-
- def hms(self):
- """Split time into hours, minutes and seconeds"""
- hhh = int(abs(self) / 3600)
- mmm = int((abs(self) % 3600) / 60)
- sss = abs(self) % 60
- return hhh, mmm, sss
-
- def __str__(self):
- if self != self:
- return "nan"
- hh, mm, ss = self.hms()
- sign = '-' if self < 0 else ''
- if hh > 0:
- return '{}{:d}:{:02d}:{:02.0f}'.format(sign, hh, mm, ss)
- elif mm > 0:
- return '{}{:d}:{:04.1f}'.format(sign, mm, ss)
- elif ss > 1:
- return '{}{:.1f} s'.format(sign, ss)
- else:
- return '{}{:.2f} s'.format(sign, ss)
-
- def gv_value(self):
- """Value formatting for visualization"""
- if self != self:
- return "null"
- hh, mm, ss = self.hms()
- return [hh, mm, int(ss), int(ss*1000) % 1000]
-
-
-class SizeVal(MeasurementVal):
- """Class representing time values"""
- quantity = 'size'
- gv_title = 'size in MiB'
- gv_data_type = 'number'
-
- def __str__(self):
- if self != self:
- return "nan"
- if abs(self) < 1024:
- return '{:.1f} kiB'.format(self)
- elif abs(self) < 1048576:
- return '{:.2f} MiB'.format(self / 1024)
- else:
- return '{:.2f} GiB'.format(self / 1048576)
-
- def gv_value(self):
- """Value formatting for visualization"""
- if self != self:
- return "null"
- return self / 1024
-
-def measurement_stats(meas, prefix=''):
- """Get statistics of a measurement"""
- if not meas:
- return {prefix + 'sample_cnt': 0,
- prefix + 'mean': MeasurementVal('nan'),
- prefix + 'stdev': MeasurementVal('nan'),
- prefix + 'variance': MeasurementVal('nan'),
- prefix + 'min': MeasurementVal('nan'),
- prefix + 'max': MeasurementVal('nan'),
- prefix + 'minus': MeasurementVal('nan'),
- prefix + 'plus': MeasurementVal('nan')}
-
- stats = {'name': meas['name']}
- if meas['type'] == 'sysres':
- val_cls = TimeVal
- values = meas['values']['elapsed_time']
- elif meas['type'] == 'diskusage':
- val_cls = SizeVal
- values = meas['values']['size']
- else:
- raise Exception("Unknown measurement type '{}'".format(meas['type']))
- stats['val_cls'] = val_cls
- stats['quantity'] = val_cls.quantity
- stats[prefix + 'sample_cnt'] = len(values)
-
- mean_val = val_cls(mean(values))
- min_val = val_cls(min(values))
- max_val = val_cls(max(values))
-
- stats[prefix + 'mean'] = mean_val
- if len(values) > 1:
- stats[prefix + 'stdev'] = val_cls(stdev(values))
- stats[prefix + 'variance'] = val_cls(variance(values))
- else:
- stats[prefix + 'stdev'] = float('nan')
- stats[prefix + 'variance'] = float('nan')
- stats[prefix + 'min'] = min_val
- stats[prefix + 'max'] = max_val
- stats[prefix + 'minus'] = val_cls(mean_val - min_val)
- stats[prefix + 'plus'] = val_cls(max_val - mean_val)
-
- return stats
-
diff --git a/import-layers/yocto-poky/scripts/lib/build_perf/scrape-html-report.js b/import-layers/yocto-poky/scripts/lib/build_perf/scrape-html-report.js
deleted file mode 100644
index 05a1f5700..000000000
--- a/import-layers/yocto-poky/scripts/lib/build_perf/scrape-html-report.js
+++ /dev/null
@@ -1,56 +0,0 @@
-var fs = require('fs');
-var system = require('system');
-var page = require('webpage').create();
-
-// Examine console log for message from chart drawing
-page.onConsoleMessage = function(msg) {
- console.log(msg);
- if (msg === "ALL CHARTS READY") {
- window.charts_ready = true;
- }
- else if (msg.slice(0, 11) === "CHART READY") {
- var chart_id = msg.split(" ")[2];
- console.log('grabbing ' + chart_id);
- var png_data = page.evaluate(function (chart_id) {
- var chart_div = document.getElementById(chart_id + '_png');
- return chart_div.outerHTML;
- }, chart_id);
- fs.write(args[2] + '/' + chart_id + '.png', png_data, 'w');
- }
-};
-
-// Check command line arguments
-var args = system.args;
-if (args.length != 3) {
- console.log("USAGE: " + args[0] + " REPORT_HTML OUT_DIR\n");
- phantom.exit(1);
-}
-
-// Open the web page
-page.open(args[1], function(status) {
- if (status == 'fail') {
- console.log("Failed to open file '" + args[1] + "'");
- phantom.exit(1);
- }
-});
-
-// Check status every 100 ms
-interval = window.setInterval(function () {
- //console.log('waiting');
- if (window.charts_ready) {
- clearTimeout(timer);
- clearInterval(interval);
-
- var fname = args[1].replace(/\/+$/, "").split("/").pop()
- console.log("saving " + fname);
- fs.write(args[2] + '/' + fname, page.content, 'w');
- phantom.exit(0);
- }
-}, 100);
-
-// Time-out after 10 seconds
-timer = window.setTimeout(function () {
- clearInterval(interval);
- console.log("ERROR: timeout");
- phantom.exit(1);
-}, 10000);
OpenPOWER on IntegriCloud