compare.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. const path = require('path');
  3. const fs = require('fs');
  4. const Table = require('cli-table2');
  5. const chalk = require('chalk');
  6. let files = fs.readdirSync(path.join(__dirname, '.results'))
  7. .map(file => {
  8. const result = JSON.parse(fs.readFileSync(path.join(__dirname, '.results', file), 'utf8'));
  9. result['.file'] = path.basename(file, '.json');
  10. return result;
  11. })
  12. // Find the most recent benchmark runs
  13. .sort((fileA, fileB) => fileB['.time'] - fileA['.time']);
  14. function average(data) {
  15. const sum = data.reduce((sum, value) => sum + value, 0);
  16. const avg = sum / data.length;
  17. return avg;
  18. }
  19. function standardDeviation(values) {
  20. const avg = average(values);
  21. const squareDiffs = values.map(value => {
  22. const diff = value - avg;
  23. const sqrDiff = diff * diff;
  24. return sqrDiff;
  25. });
  26. const avgSquareDiff = average(squareDiffs);
  27. const stdDev = Math.sqrt(avgSquareDiff);
  28. return stdDev;
  29. }
  30. // Only the 3 most recent runs
  31. files = files.slice(0, 3);
  32. function prepStats(times) {
  33. times = times
  34. .map(time => time.time)
  35. .sort((timeA, timeB) => timeA - timeB);
  36. // Remove fastest and slowest
  37. times = times.slice(1, times.length - 1);
  38. const sum = times.reduce((a, b) => a + b, 0);
  39. return {
  40. mean: Math.round((sum / times.length) * 1000) / 1000,
  41. median: times[Math.floor(times.length / 2)],
  42. stdDev: standardDeviation(times).toFixed(4),
  43. min: times[0],
  44. max: times[times.length - 1]
  45. };
  46. }
  47. const results = {};
  48. const fileNames = files.map(file => file['.file']);
  49. const stats = ['mean', 'stdDev', 'median', 'min', 'max'];
  50. files.forEach(file => {
  51. Object.keys(file)
  52. .filter(key => !/^\./.test(key))
  53. .forEach(key => {
  54. results[key] = results[key] || {};
  55. results[key][file['.file']] = prepStats(file[key]);
  56. });
  57. });
  58. const table = new Table();
  59. table.push(
  60. [''].concat(stats.map(stat => {
  61. return {
  62. content: stat,
  63. colSpan: fileNames.length,
  64. hAlign: 'center'
  65. };
  66. })),
  67. stats.reduce(arr => arr.concat(fileNames), ['args'])
  68. );
  69. Object.keys(results)
  70. .forEach(key => {
  71. table.push(stats.reduce((arr, stat) => {
  72. let min = Infinity;
  73. let max = -Infinity;
  74. const statGroup = fileNames.map(fileName => {
  75. let result = results[key][fileName];
  76. result = result && result[stat];
  77. if (result) {
  78. min = Math.min(min, result);
  79. max = Math.max(max, result);
  80. return result;
  81. }
  82. return '';
  83. });
  84. return arr.concat(statGroup.map(stat => {
  85. if (stat === min) {
  86. return chalk.green(stat);
  87. }
  88. if (stat === max) {
  89. return chalk.red(stat);
  90. }
  91. return stat;
  92. }));
  93. }, [key]));
  94. });
  95. console.log(table.toString());