Skip to content

Commit

Permalink
Split file
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Dec 12, 2021
1 parent c1b84a5 commit f34e3ab
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 84 deletions.
86 changes: 86 additions & 0 deletions src/stats/cold/find.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Compute the mean incrementally, measure by measure.
// Then retrieve the `incrementalMean` that is the closest to the total `mean`,
// within a specific range decided by `minIndex` and `maxIndex`.
// This must be performend on unsorted `measures`.
// - Therefore, outliers are still present and must be removed using a `filter`
// - This also requires using two indexes: filtered and not.
// `minIndex` is always <= `maxIndex`, i.e. a `closestMean` is always found.
// Time complexity is `O(n)`.
// Memory complexity is `O(1)` and very low by using a streaming logic.
// This is optimized for performance, which explains the usage of imperative
// programming patterns.
/* eslint-disable max-statements, complexity, fp/no-let, fp/no-loops,
fp/no-mutation, max-depth, no-continue */
export const findClosestMean = function (
array,
{ mean, minIndex, maxIndex, filter },
) {
let sum = 0
let filteredIndex = 0
let closestMean = 0
let closestMeanDiff = Number.POSITIVE_INFINITY

for (const value of array) {
if (!filter(value)) {
continue
}

if (filteredIndex > maxIndex) {
break
}

filteredIndex += 1
sum += value

if (filteredIndex <= minIndex) {
continue
}

const incrementalMean = sum / filteredIndex
const meanDiff = Math.abs(mean - incrementalMean)

if (closestMeanDiff > meanDiff) {
closestMeanDiff = meanDiff
closestMean = incrementalMean
}
}

return closestMean
}

// Find the index of the first `incrementalMean` between `incrementalMeanMin`
// and `incrementalMax`.
export const findHotIndex = function (
array,
{ minIndex, filter, incrementalMeanMin, incrementalMeanMax },
) {
let sum = 0
let filteredIndex = 0
let incrementalMean = 0

for (const value of array) {
if (!filter(value)) {
continue
}

filteredIndex += 1
sum += value

if (filteredIndex <= minIndex) {
continue
}

incrementalMean = sum / filteredIndex

if (
incrementalMean >= incrementalMeanMin &&
incrementalMean <= incrementalMeanMax
) {
break
}
}

return filteredIndex - 1
}
/* eslint-enable max-statements, complexity, fp/no-let, fp/no-loops,
fp/no-mutation, max-depth, no-continue */
86 changes: 2 additions & 84 deletions src/stats/cold/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { getMean } from '../sum.js'

import { findClosestMean, findHotIndex } from './find.js'

// Tasks usually get faster as they repeat
// - This is due to optimization at the enginer or OS level.
// This means a benchmark might end too early, while the task is still getting
Expand Down Expand Up @@ -108,87 +110,3 @@ const getLengthFromIndex = function (percentage, index) {
// make `cold` fluctuate more once `incrementalMean` has stabilized.
const COLD_MIN_PERCENTAGE = 0.1
const COLD_MAX_PERCENTAGE = 0.6

// Compute the mean incrementally, measure by measure.
// Then retrieve the `incrementalMean` that is the closest to the total `mean`,
// within a specific range decided by `minIndex` and `maxIndex`.
// This must be performend on unsorted `measures`.
// - Therefore, outliers are still present and must be removed using a `filter`
// - This also requires using two indexes: filtered and not.
// `minIndex` is always <= `maxIndex`, i.e. a `closestMean` is always found.
// Time complexity is `O(n)`.
// Memory complexity is `O(1)` and very low by using a streaming logic.
// This is optimized for performance, which explains the usage of imperative
// programming patterns.
/* eslint-disable max-statements, complexity, fp/no-let, fp/no-loops,
fp/no-mutation, max-depth, no-continue */
const findClosestMean = function (array, { mean, minIndex, maxIndex, filter }) {
let sum = 0
let filteredIndex = 0
let closestMean = 0
let closestMeanDiff = Number.POSITIVE_INFINITY

for (const value of array) {
if (!filter(value)) {
continue
}

if (filteredIndex > maxIndex) {
break
}

filteredIndex += 1
sum += value

if (filteredIndex <= minIndex) {
continue
}

const incrementalMean = sum / filteredIndex
const meanDiff = Math.abs(mean - incrementalMean)

if (closestMeanDiff > meanDiff) {
closestMeanDiff = meanDiff
closestMean = incrementalMean
}
}

return closestMean
}

// Find the index of the first `incrementalMean` between `incrementalMeanMin`
// and `incrementalMax`.
const findHotIndex = function (
array,
{ minIndex, filter, incrementalMeanMin, incrementalMeanMax },
) {
let sum = 0
let filteredIndex = 0
let incrementalMean = 0

for (const value of array) {
if (!filter(value)) {
continue
}

filteredIndex += 1
sum += value

if (filteredIndex <= minIndex) {
continue
}

incrementalMean = sum / filteredIndex

if (
incrementalMean >= incrementalMeanMin &&
incrementalMean <= incrementalMeanMax
) {
break
}
}

return filteredIndex - 1
}
/* eslint-enable max-statements, complexity, fp/no-let, fp/no-loops,
fp/no-mutation, max-depth, no-continue */

0 comments on commit f34e3ab

Please sign in to comment.