1/**
2 * Command line application to process the output of
3 *   make skps_release_and_SIMD
4 * and present some statistical results in a human-readable table format.
5 */
6
7const fs = require('fs');
8
9// These files are the output of `make skps_release_and_SIMD`
10const SIMD_DATA = JSON.parse(fs.readFileSync('simd_out.json', 'utf8'));
11const RELEASE_DATA = JSON.parse(fs.readFileSync('release_out.json', 'utf8'));
12
13let skp_names = new Set();
14for (const key of Object.keys(SIMD_DATA)) {
15    skp_names.add(key)
16}
17for (const key of Object.keys(RELEASE_DATA)) {
18    skp_names.add(key)
19}
20
21let simd_frame_average_accumulator = 0;
22let simd_frame_median_accumulator = 0;
23let release_frame_average_accumulator = 0;
24let release_frame_median_accumulator = 0;
25const comparisonData = [];
26
27for (const skp_name of skp_names) {
28    if (SIMD_DATA[skp_name] && RELEASE_DATA[skp_name]) {
29        // note: frames are frametimes, measured in ms
30        const simd_frames = SIMD_DATA[skp_name].total_frame_ms;
31        const simd_frames_average = averageFromArray(simd_frames);
32        const simd_frames_median = medianFromArray(simd_frames);
33        simd_frame_average_accumulator += simd_frames_average;
34        simd_frame_median_accumulator += simd_frames_median;
35
36        const release_frames = RELEASE_DATA[skp_name].total_frame_ms;
37        const release_frames_average = averageFromArray(release_frames);
38        const release_frames_median = medianFromArray(release_frames);
39        release_frame_average_accumulator += release_frames_average;
40        release_frame_median_accumulator += release_frames_median;
41
42        comparisonData.push({
43            skp_name: skp_name,
44            frames_average_difference: release_frames_average - simd_frames_average,
45            frames_median_difference: release_frames_median - simd_frames_median,
46            simd_frames_median: simd_frames_median,
47            simd_frames_average: simd_frames_average,
48            release_frames_average: release_frames_average,
49            release_frames_median: release_frames_median
50        });
51    }
52}
53const simd_average_frame = simd_frame_average_accumulator / comparisonData.length;
54const simd_skps_median_frame = simd_frame_median_accumulator / comparisonData.length;
55const release_average_frame = release_frame_average_accumulator / comparisonData.length;
56const release_median_frame = release_frame_median_accumulator / comparisonData.length;
57
58console.log('\nAverages across all SKP files');
59console.table({
60    'Average frame time average': {
61        'release CanvasKit build (ms)': release_average_frame.toFixed(2),
62        'experimental_simd CanvasKit build (ms)': simd_average_frame.toFixed(2),
63        'difference (ms)': (release_average_frame - simd_average_frame).toFixed(2)
64    },
65    'Median frame time average': {
66        'release CanvasKit build (ms)': release_median_frame.toFixed(2),
67        'experimental_simd CanvasKit build (ms)': simd_skps_median_frame.toFixed(2),
68        'difference (ms)': (release_median_frame - simd_skps_median_frame).toFixed(2)
69    }
70});
71
72const frameTimeMedianDifferenceSorted =
73    comparisonData.sort(
74        ({frames_median_difference: m1}, {frames_median_difference: m2}) => m2 - m1
75    );
76
77console.log('\nBest 3 Individual SKP frame time median differences in favor of the SIMD build');
78console.table(
79    frameTimeMedianDifferenceSorted
80    .map(tableDataFromComparisonDataObject)
81    .slice(0,3)
82);
83
84console.log('\nWorst 3 Individual SKP frame time median differences NOT in favor of the SIMD build');
85console.table(
86    frameTimeMedianDifferenceSorted
87    .map(tableDataFromComparisonDataObject)
88    .reverse().slice(0,3)
89);
90
91function averageFromArray(array) {
92    return array.reduce((a, b) => a+b, 0) / array.length;
93}
94function medianFromArray(array) {
95    return array.sort((a,b) => a-b)[Math.floor(array.length/2)];
96}
97
98function tableDataFromComparisonDataObject({
99    skp_name,
100    frames_median_difference,
101    simd_frames_median,
102    release_frames_median
103}) {
104    return {
105        '.SKP name': skp_name,
106        'release CanvasKit build (ms)': release_frames_median.toFixed(2),
107        'experimental_simd CanvasKit build (ms)': simd_frames_median.toFixed(2),
108        'difference (ms)': frames_median_difference.toFixed(2)
109    };
110}