|
2 | 2 | const humanizeNumber = require('humanize-number') |
3 | 3 | const pluralize = require('pluralize') |
4 | 4 |
|
5 | | -module.exports = (benchmark) => { |
| 5 | +/** |
| 6 | + * Computes the arithmetic mean of a sample. |
| 7 | + * https://github.com/bestiejs/benchmark.js/blob/42f3b732bac3640eddb3ae5f50e445f3141016fd/benchmark.js |
| 8 | + * @private |
| 9 | + * @param {Array} sample The sample. |
| 10 | + * @returns {number} The mean. |
| 11 | + */ |
| 12 | +function getMean(sample = []) { |
| 13 | + return sample.reduce((sum, x) => sum + x, 0) / sample.length |
| 14 | +} |
| 15 | + |
| 16 | +function bytesToSize(bytes) { |
| 17 | + var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'] |
| 18 | + if (bytes == 0) return '0 Byte' |
| 19 | + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))) |
| 20 | + return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i] |
| 21 | +} |
| 22 | + |
| 23 | +/** |
| 24 | + * T-Distribution two-tailed critical values for 95% confidence. |
| 25 | + * For more info see http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm. |
| 26 | + */ |
| 27 | +const tTable = { |
| 28 | + 1: 12.706, |
| 29 | + 2: 4.303, |
| 30 | + 3: 3.182, |
| 31 | + 4: 2.776, |
| 32 | + 5: 2.571, |
| 33 | + 6: 2.447, |
| 34 | + 7: 2.365, |
| 35 | + 8: 2.306, |
| 36 | + 9: 2.262, |
| 37 | + 10: 2.228, |
| 38 | + 11: 2.201, |
| 39 | + 12: 2.179, |
| 40 | + 13: 2.16, |
| 41 | + 14: 2.145, |
| 42 | + 15: 2.131, |
| 43 | + 16: 2.12, |
| 44 | + 17: 2.11, |
| 45 | + 18: 2.101, |
| 46 | + 19: 2.093, |
| 47 | + 20: 2.086, |
| 48 | + 21: 2.08, |
| 49 | + 22: 2.074, |
| 50 | + 23: 2.069, |
| 51 | + 24: 2.064, |
| 52 | + 25: 2.06, |
| 53 | + 26: 2.056, |
| 54 | + 27: 2.052, |
| 55 | + 28: 2.048, |
| 56 | + 29: 2.045, |
| 57 | + 30: 2.042, |
| 58 | + infinity: 1.96, |
| 59 | +} |
| 60 | + |
| 61 | +/** https://github.com/bestiejs/benchmark.js/blob/42f3b732bac3640eddb3ae5f50e445f3141016fd/benchmark.js */ |
| 62 | +function getRme(sample, mean) { |
| 63 | + const varOf = function (sum, x) { |
| 64 | + return sum + Math.pow(x - mean, 2) |
| 65 | + } |
| 66 | + // Compute the sample variance (estimate of the population variance). |
| 67 | + const variance = sample.reduce(varOf, 0) / (sample.length - 1) || 0 |
| 68 | + // Compute the sample standard deviation (estimate of the population standard deviation). |
| 69 | + const sd = Math.sqrt(variance) |
| 70 | + // Compute the standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean). |
| 71 | + const sem = sd / Math.sqrt(sample.length) |
| 72 | + // Compute the degrees of freedom. |
| 73 | + const df = sample.length - 1 |
| 74 | + // Compute the critical value. |
| 75 | + const critical = tTable[Math.round(df) || 1] || tTable.infinity |
| 76 | + // Compute the margin of error. |
| 77 | + const moe = sem * critical |
| 78 | + // Compute the relative margin of error. |
| 79 | + const rme = (moe / mean) * 100 || 0 |
| 80 | + return rme |
| 81 | +} |
| 82 | + |
| 83 | +module.exports = (benchmark, heapSizeMeasurements, objectCountMeasurements) => { |
6 | 84 | const ops = benchmark.hz // Can be null on the first run if it executes really quickly |
7 | 85 | ? humanizeNumber(benchmark.hz.toFixed(benchmark.hz < 100 ? 2 : 0)) |
8 | 86 | : 0 |
9 | 87 | const marginOfError = benchmark.stats.rme.toFixed(2) |
10 | 88 | const runs = pluralize('run', benchmark.stats.sample.length, true) |
11 | | - return `${ops} ops/sec ±${marginOfError}% (${runs} sampled)` |
| 89 | + let s = `${runs} sampled: ${ops} ops/sec ±${marginOfError}%` |
| 90 | + if (heapSizeMeasurements && heapSizeMeasurements.length) { |
| 91 | + const averageRam = getMean(heapSizeMeasurements) |
| 92 | + const ramMarginOfError = getRme(heapSizeMeasurements, averageRam).toFixed(2) |
| 93 | + s += ` / RAM: ${bytesToSize(averageRam)} ±${ramMarginOfError}%` |
| 94 | + } |
| 95 | + if (objectCountMeasurements && objectCountMeasurements.length) { |
| 96 | + const averageObjectsCount = getMean(objectCountMeasurements) |
| 97 | + const objectsCountMarginOfError = getRme( |
| 98 | + objectCountMeasurements, |
| 99 | + averageObjectsCount |
| 100 | + ).toFixed(2) |
| 101 | + s += ` / Objects: ${averageObjectsCount.toFixed( |
| 102 | + 0 |
| 103 | + )} ±${objectsCountMarginOfError}%` |
| 104 | + } |
| 105 | + return s |
12 | 106 | } |
0 commit comments