Skip to content

Commit

Permalink
Add outliers configuration property
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Dec 5, 2021
1 parent 700794c commit c96cb83
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 11 deletions.
16 changes: 16 additions & 0 deletions src/bin/config/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,20 @@ after the percentage.
is node.
- Several limits can be specified at once.`,
},
outliers: {
group: TASKS,
boolean: true,
describe: `Some measures can be extremely slower than others.
Most of the times, those outliers are due to concurrent logic unrelated to
your tasks such as garbage collection or OS background processes.
Outliers lower accuracy and significantly slow down benchmarks.
Therefore, they are ignored by default.
They can be kept by setting this configuration property to "true" instead.
We recommend keeping the default behavior unless you are confident those
measures are important for the benchmark's results.
Default: false`,
},
}
1 change: 1 addition & 0 deletions src/combination/tasks/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const findTasks = async function ({
precisionTarget: 0,
cwd,
previewState: { quiet: true },
outliers: true,
stage: 'init',
noDimensions,
},
Expand Down
1 change: 1 addition & 0 deletions src/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const DEFAULT_CONFIG = {
precision: 5,
system: 'default_system',
save: false,
outliers: false,
runnerConfig: {},
reporterConfig: {},
limit: [],
Expand Down
1 change: 1 addition & 0 deletions src/dev/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const combinationDev = async function (combination, noDimensions, { cwd }) {
precisionTarget: 0,
cwd,
previewState: { quiet: true },
outliers: true,
stage: 'dev',
noDimensions,
})
Expand Down
3 changes: 2 additions & 1 deletion src/run/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ const previewAndMeasure = async function ({

const measureResult = async function ({
result,
config: { cwd, precisionTarget },
config: { cwd, precisionTarget, outliers },
previewState,
noDimensions,
}) {
const combinations = await measureCombinations(result.combinations, {
precisionTarget,
cwd,
previewState,
outliers,
stage: 'main',
noDimensions,
})
Expand Down
10 changes: 9 additions & 1 deletion src/run/measure/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const performMeasureLoop = async function ({
previewState,
stopState,
stage,
outliers,
server,
logsFd,
minLoopDuration,
Expand All @@ -44,6 +45,7 @@ export const performMeasureLoop = async function ({
performSample(state, {
previewState,
precisionTarget,
outliers,
server,
minLoopDuration,
logsFd,
Expand All @@ -66,6 +68,7 @@ const performSample = async function (
{
previewState,
precisionTarget,
outliers,
server,
minLoopDuration,
logsFd,
Expand All @@ -79,7 +82,12 @@ const performSample = async function (
{ server, minLoopDuration, targetSampleDuration },
sampleState,
)
const statsA = addStats(stats, sampleStateA, minLoopDuration)
const statsA = addStats({
stats,
sampleState: sampleStateA,
minLoopDuration,
outliers,
})
const statsB = endRunDuration(startStat, statsA)
await Promise.all([
updatePreviewStats({
Expand Down
9 changes: 5 additions & 4 deletions src/stats/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ export const getInitialStats = function () {
// last/current result)
// - outliersMin, outliersMax: >=0 <=1
// - histogram[*].end: <=1
export const addStats = function (
export const addStats = function ({
stats,
{ measures, unsortedMeasures, sampleLoops, sampleTimes },
sampleState: { measures, unsortedMeasures, sampleLoops, sampleTimes },
minLoopDuration,
) {
outliers,
}) {
if (measures.length === 0) {
return stats
}
Expand All @@ -57,7 +58,7 @@ export const addStats = function (
sampleTimes,
minLoopDuration,
})
const computedStats = computeStats(measures, unsortedMeasures)
const computedStats = computeStats(measures, unsortedMeasures, outliers)
return { ...countStats, ...computedStats }
}

Expand Down
6 changes: 3 additions & 3 deletions src/stats/compute.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getHistogram } from './histogram.js'
import { getLengthFromLoops } from './length.js'
import { getOutliersPercentages } from './outliers/main.js'
import { getOutliersPercentage } from './outliers/main.js'
import { getPrecisionStats } from './precision.js'
import { getSortedMedian, getQuantiles } from './quantile.js'
import { getMean } from './sum.js'
Expand Down Expand Up @@ -46,8 +46,8 @@ import { getMean } from './sum.js'
// important. However, the mean is a far more useful statistic.
// - This would create too many statistics for the average, together with the
// mean and the median.
export const computeStats = function (measures, unsortedMeasures) {
const { outliersMin, outliersMax } = getOutliersPercentages(measures)
export const computeStats = function (measures, unsortedMeasures, outliers) {
const { outliersMin, outliersMax } = getOutliersPercentage(measures, outliers)
const { minIndex, maxIndex, length } = getLengthFromLoops(
measures.length,
outliersMin,
Expand Down
21 changes: 19 additions & 2 deletions src/stats/outliers/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,25 @@ import { THRESHOLDS } from './threshold.js'
// - outliersMin|Max 0 should be possible
// - Making only slight changes to the measures should not result in big
// changes of outliersMin|Max
export const getOutliersPercentages = function (measures) {
if (measures.length <= 2) {
// Outliers removal can be skipped by using the `outliers: true` configuration
// property:
// - This is discouraged because:
// - Outliers performance is usually unrelated to the task itself,
// i.e. they decrease accuracy.
// - In many cases, this increases `stdev` a lot, which makes runs much
// longer.
// - It makes the `envDev` logic not work well.
// - However, there are a few cases where outliers are useful:
// - When a task is a mix of multiple distributions with very different
// speed, but are all significant, such as:
// - When a task slows down due to memory allocation but only at
// specific thresholds
// - `Array.push()` is an example of this
// - Tasks with custom units
// - When real `min|max` is important
// - When debugging
export const getOutliersPercentage = function (measures, outliers) {
if (measures.length <= 2 || outliers) {
return { outliersMin: 0, outliersMax: 0 }
}

Expand Down

0 comments on commit c96cb83

Please sign in to comment.