diff mbox series

[v2,1/5] oe-build-perf-report: Add apache echarts to make report interactive

Message ID 20240503144340.27385-2-ninette@thehoodiefirm.com
State Accepted, archived
Commit 63c9321832aae79d20a4ddd199a4a1385f81de53
Headers show
Series Improvements for performance test report view | expand

Commit Message

Ninette Adhikari May 3, 2024, 2:43 p.m. UTC
From: Ninette Adhikari <13760198+ninetteadhikari@users.noreply.github.com>

- Add Apache echarts (https://echarts.apache.org/en/index.html) library to create build performance charts.
- Restructure data to time and value array format so that it can be used by echarts.
- This commit also converts test duration to minutes to map against the values axis.
- Zoom is added to the line charts.
---
 .../build_perf/html/measurement_chart.html    | 116 +++++++++++-------
 scripts/lib/build_perf/html/report.html       |   6 +-
 2 files changed, 72 insertions(+), 50 deletions(-)

Comments

Richard Purdie May 15, 2024, 3:56 p.m. UTC | #1
On Fri, 2024-05-03 at 16:43 +0200, Ninette Adhikari wrote:
> From: Ninette Adhikari <13760198+ninetteadhikari@users.noreply.github.com>
> 
> - Add Apache echarts (https://echarts.apache.org/en/index.html) library to create build performance charts.
> - Restructure data to time and value array format so that it can be used by echarts.
> - This commit also converts test duration to minutes to map against the values axis.
> - Zoom is added to the line charts.
> ---
>  .../build_perf/html/measurement_chart.html    | 116 +++++++++++-------
>  scripts/lib/build_perf/html/report.html       |   6 +-
>  2 files changed, 72 insertions(+), 50 deletions(-)

Thanks, I was able to test these:

https://autobuilder.yocto.io/pub/non-release/20240514-17/testresults/buildperf-alma8/perf-alma8_master-next_20240514121350_a8f48d1cb1.html
https://autobuilder.yocto.io/pub/non-release/20240514-16/testresults/buildperf-debian11/perf-debian11_master-next_20240514051235_a8f48d1cb1.html

and they are definitely a huge improvement on what we had.

I've merged them since I think at this point they're definitely better,
thanks for making the tweaks others asked about.

As Ross mentioned, the preview doesn't always quite match the chart
itself.

The other question we'd wondered about is whether we can show the
commit hash as well as the commit number?

The tricky part is that ideally we'd be able to copy/paste the hash or
even make it a clickable link to the poky repository
(e.g.https://git.yoctoproject.org/poky/commit/?id=6582436a1d1af7775a6bb651aff47a9db773e32b
) but I'm not sure how possible that is?

The use case here is where for example there are the step changes in
things like disk usage, or the kernel build time, we'd like to know
which changes happened around that time. The commit number is good, and
you can resolve it with a command like:

git rev-list --reverse HEAD | nl -n ln | grep ^69808

but a direct link to the revision would be ideal if possible.

Regardless, this looks very very much improved on where it was, thanks!

Cheers,

Richard
Ross Burton May 15, 2024, 4 p.m. UTC | #2
On 15 May 2024, at 16:56, Richard Purdie via lists.openembedded.org <richard.purdie=linuxfoundation.org@lists.openembedded.org> wrote:
> The other question we'd wondered about is whether we can show the
> commit hash as well as the commit number?
> 
> The tricky part is that ideally we'd be able to copy/paste the hash or
> even make it a clickable link to the poky repository
> (e.g.https://git.yoctoproject.org/poky/commit/?id=6582436a1d1af7775a6bb651aff47a9db773e32b
> ) but I'm not sure how possible that is?
> 
> The use case here is where for example there are the step changes in
> things like disk usage, or the kernel build time, we'd like to know
> which changes happened around that time. The commit number is good, and
> you can resolve it with a command like:
> 
> git rev-list --reverse HEAD | nl -n ln | grep ^69808
> 
> but a direct link to the revision would be ideal if possible.

A better way - if you already have access to the results.json for a particular run then metadata.json contains all the SHAs that were used.

Ross
diff mbox series

Patch

diff --git a/scripts/lib/build_perf/html/measurement_chart.html b/scripts/lib/build_perf/html/measurement_chart.html
index 65f1a227ad..ffec3d09db 100644
--- a/scripts/lib/build_perf/html/measurement_chart.html
+++ b/scripts/lib/build_perf/html/measurement_chart.html
@@ -1,50 +1,76 @@ 
-<script type="text/javascript">
-  chartsDrawing += 1;
-  google.charts.setOnLoadCallback(drawChart_{{ chart_elem_id }});
-  function drawChart_{{ chart_elem_id }}() {
-    var data = new google.visualization.DataTable();
+<script type="module">
+  // Get raw data
+  const rawData = [
+    {% for sample in measurement.samples %}
+      [{{ sample.commit_num }}, {{ sample.mean.gv_value() }}, {{ sample.start_time }}],
+    {% endfor %}
+  ];
 
-    // 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 },
-    };
+  const convertToMinute = (time) => {
+    return time[0]*60 + time[1] + time[2]/60 + time[3]/3600;
+  }
 
-    // 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 %}
-    ]);
+  // Convert raw data to the format: [time, value]
+  const data = rawData.map(([commit, value, time]) => {
+    return [
+      new Date(time * 1000).getTime(), // The Date object takes values in milliseconds rather than seconds. So to use a Unix timestamp we have to multiply it by 1000.
+      Array.isArray(value) ? convertToMinute(value) : value // Assuming the array values are duration in the format [hours, minutes, seconds, milliseconds]
+    ]
+  });
 
-    // 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);
-}
+  // Set chart options
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      position: function (pt) {
+        return [pt[0], '10%'];
+      },
+      valueFormatter: (value) => value.toFixed(2)
+    },
+    xAxis: {
+      type: 'time',
+    },
+    yAxis: {
+      name: '{{ measurement.value_type.quantity }}' == 'time' ? 'Duration (minutes)' : 'Disk size (MB)',
+      type: 'value',
+      min: function(value) {
+        return Math.round(value.min - 0.5);
+      },
+      max: function(value) {
+        return Math.round(value.max + 0.5);
+      }
+    },
+    dataZoom: [
+      {
+        type: 'inside',
+        start: 0,
+        end: 100
+      },
+      {
+        start: 0,
+        end: 100
+      }
+    ],
+    series: [
+      {
+        name: '{{ measurement.value_type.quantity }}',
+        type: 'line',
+        smooth: true,
+        symbol: 'none',
+        data: data
+      }
+    ]
+  };
+
+  // Draw chart
+  const chart_div = document.getElementById('{{ chart_elem_id }}');
+  const measurement_chart= echarts.init(chart_div, null, {
+    height: 320
+  });
+  // Change chart size with browser resize
+  window.addEventListener('resize', function() {
+    measurement_chart.resize();
+  });
+  measurement_chart.setOption(option);
 </script>
 
diff --git a/scripts/lib/build_perf/html/report.html b/scripts/lib/build_perf/html/report.html
index d1ba6f2578..653fd985bc 100644
--- a/scripts/lib/build_perf/html/report.html
+++ b/scripts/lib/build_perf/html/report.html
@@ -3,11 +3,7 @@ 
 <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>
+<script src=" https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js "></script>
 
 {# Render measurement result charts #}
 {% for test in test_data %}