4
0

timing.cjs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // NOTICE: This file is generated by Rollup. To modify it,
  2. // please instead edit the ESM counterpart and rebuild with Rollup (npm run build).
  3. 'use strict';
  4. const process = require('node:process');
  5. const table = require('table');
  6. // Inspired by ESLint's timing.js
  7. // https://github.com/eslint/eslint/blob/09bc2a88c00aa9a93c7de505795fc4e85b2e6357/lib/linter/timing.js
  8. /**
  9. * Start time measurement.
  10. * @returns {bigint} Variable for tracking time in nanoseconds.
  11. */
  12. function startTime() {
  13. return process.hrtime.bigint();
  14. }
  15. /**
  16. * End time measurement.
  17. * @param {bigint} start Variable for tracking time in nanoseconds.
  18. * @returns {number} The measured time in milliseconds.
  19. */
  20. function endTime(start) {
  21. const diff = process.hrtime.bigint() - start;
  22. return Number(diff) / 1e6;
  23. }
  24. const HEADERS = ['#', 'Rule', 'Time (ms)', 'Relative'];
  25. /**
  26. * Decide how many rules to show in the output list.
  27. * @returns {number} The number of rules to show.
  28. */
  29. function getListSize() {
  30. const TIMING = process.env.TIMING;
  31. if (typeof TIMING === 'undefined') {
  32. return 0;
  33. }
  34. if (TIMING.toLowerCase() === 'all') {
  35. return Number.POSITIVE_INFINITY;
  36. }
  37. const parsed = Number.parseInt(TIMING, 10);
  38. if (!Number.isNaN(parsed) && parsed >= 1) {
  39. return parsed;
  40. }
  41. return 0;
  42. }
  43. const listSize = getListSize();
  44. const enabled = listSize !== 0;
  45. /** @type {import('table').TableUserConfig} */
  46. const tableConfig = {
  47. columns: [
  48. { alignment: 'right' },
  49. { alignment: 'left' },
  50. { alignment: 'right' },
  51. { alignment: 'right' },
  52. ],
  53. };
  54. /**
  55. * Display the timing data.
  56. * @param {{ [key: string]: number }} data Data object to be displayed.
  57. * @returns {void}
  58. * @private
  59. */
  60. function display(data) {
  61. let total = 0;
  62. /** @type {Array<[string, number]>} */
  63. const rows = Object.keys(data).map((key) => {
  64. const t = data[key] ?? 0;
  65. total += t;
  66. return [key, t];
  67. });
  68. rows.sort((a, b) => b[1] - a[1]);
  69. const limitedRows = rows.slice(0, listSize);
  70. // Format rows with percentages
  71. const formattedRows = limitedRows.map((row, index) => {
  72. const percentage = total > 0 ? `${((row[1] * 100) / total).toFixed(1)}%` : '0.0%';
  73. const timeStr = row[1].toFixed(3);
  74. return [index + 1, row[0], timeStr, percentage];
  75. });
  76. formattedRows.unshift(HEADERS);
  77. // eslint-disable-next-line no-console
  78. console.log(table.table(formattedRows, tableConfig));
  79. }
  80. /** @type {{ [key: string]: number }} */
  81. const data = Object.create(null);
  82. /**
  83. * Time the execution of a function.
  84. * @param {string} key Key from the data object.
  85. * @param {Function} fn Function to be called.
  86. * @returns {Function} Function to be executed.
  87. * @private
  88. */
  89. function time(key, fn) {
  90. return function timedFunction(/** @type {any} */ ...args) {
  91. const t = startTime();
  92. const result = fn(...args);
  93. const timeDiff = endTime(t);
  94. data[key] = (data[key] ?? 0) + timeDiff;
  95. return result;
  96. };
  97. }
  98. if (enabled) {
  99. process.on('exit', () => {
  100. display(data);
  101. });
  102. }
  103. const timing = {
  104. display,
  105. enabled,
  106. getListSize,
  107. tableConfig,
  108. time,
  109. };
  110. module.exports = timing;