Skip to content

Commit

Permalink
feat: add perf test comparing the performance of web workers and curr…
Browse files Browse the repository at this point in the history
…ent algorithm
  • Loading branch information
mauriciopoppe committed Dec 18, 2023
1 parent 2f79d7a commit 7bcd588
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 132 deletions.
79 changes: 8 additions & 71 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
"babel-eslint": "^10.1.0",
"babel-loader": "^9.1.2",
"babel-plugin-transform-import-meta": "^2.2.1",
"benchmark": "^2.1.4",
"core-js": "^3.25.2",
"dox": "^1.0.0",
"eslint": "^8.23.1",
Expand Down Expand Up @@ -113,6 +112,7 @@
"standard": "^17.0.0",
"standardx": "^7.0.0",
"storybook": "^7.0.20",
"tinybench": "^2.5.1",
"ts-jest": "^29.1.1",
"ts-jest-mock-import-meta": "^1.1.0",
"ts-loader": "^9.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/derivative.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { select as d3Select, Selection } from 'd3-selection'

import { polyline } from '../graph-types/'
import { builtIn as builtInEvaluator } from './eval'
import { builtIn as builtInEvaluator } from './eval.mjs'
import datumDefaults from '../datum-defaults'
import utils from '../utils'

Expand Down
14 changes: 7 additions & 7 deletions src/helpers/eval.ts → src/helpers/eval.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const samplers = {
}

// getMathJS returns checks if mathjs is loaded.
function getMathJS(): { compile: any } | null {
function getMathJS() {
if (typeof global === 'object' && 'math' in global) {
// @ts-ignore
return global.math as any
return global.math
}
if (typeof window === 'object' && 'math' in window) {
// @ts-ignore
Expand All @@ -25,8 +25,8 @@ if (mathJS) {
samplers.builtIn = mathJS.compile
}

function generateEvaluator(samplerName: 'interval' | 'builtIn') {
function doCompile(expression: string | { eval: (scope: any) => any }) {
function generateEvaluator(samplerName) {
function doCompile(expression) {
// compiles does the following
//
// when expression === string
Expand Down Expand Up @@ -63,7 +63,7 @@ function generateEvaluator(samplerName: 'interval' | 'builtIn') {
}
}

function compileIfPossible(meta: any, property: string) {
function compileIfPossible(meta, property) {
// compile the function using interval arithmetic, cache the result
// so that multiple calls with the same argument don't trigger the
// kinda expensive compilation process
Expand All @@ -76,7 +76,7 @@ function generateEvaluator(samplerName: 'interval' | 'builtIn') {
}
}

function getCompiledExpression(meta: any, property: string) {
function getCompiledExpression(meta, property) {
return meta[samplerName + '_Compiled_' + property]
}

Expand All @@ -93,7 +93,7 @@ function generateEvaluator(samplerName: 'interval' | 'builtIn') {
* @param variables
* @returns The builtIn evaluator returns a number, the interval evaluator an array
*/
function evaluate(meta: any, property: string, variables: object) {
function evaluate(meta, property, variables) {
// e.g.
//
// meta: {
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/secant.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { select as d3Select, Selection } from 'd3-selection'

import { builtIn as builtInEvaluator } from './eval'
import { builtIn as builtInEvaluator } from './eval.mjs'
import datumDefaults from '../datum-defaults'
import { polyline } from '../graph-types/'
import utils from '../utils'
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Chart, ChartMeta, ChartMetaMargin } from './chart'

import globals, { registerGraphType } from './globals'
import { polyline, interval, scatter, text } from './graph-types'
import { interval as intervalEval, builtIn as builtInEval } from './helpers/eval'
import { interval as intervalEval, builtIn as builtInEval } from './helpers/eval.mjs'

// register common graphTypes on library load.
registerGraphType('polyline', polyline)
Expand Down Expand Up @@ -51,7 +51,7 @@ functionPlot.withWebWorkers = withWebWorkers
export * from './types'
export { Chart, ChartMeta, ChartMetaMargin }
export { registerGraphType, withWebWorkers }
export { builtIn as EvalBuiltIn, interval as EvalInterval } from './helpers/eval'
export { builtIn as EvalBuiltIn, interval as EvalInterval } from './helpers/eval.mjs'
export { TGlobals } from './globals'
export {
interval as GraphTypeInterval,
Expand Down
73 changes: 36 additions & 37 deletions src/perf/interval-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
* the design is at /design/pipeline.md
*/

// @ts-ignore
import Benchmark from 'benchmark'
import { Bench } from 'tinybench'
import { scaleLinear } from 'd3-scale'

import globals from '../globals'
import { IntervalWorkerPool } from '../samplers/interval_worker_pool'
import { FunctionPlotDatum, FunctionPlotOptionsAxis } from '../types'
import { createPathD } from '../graph-types/interval'
import { syncSamplerInterval } from '../samplers/interval'
import { asyncSamplerInterval, syncSamplerInterval } from '../samplers/interval'

function createData(nSamples: number) {
async function createData(nSamples: number, async: boolean) {
const width = 500
const height = 300
const xDomain: [number, number] = [-5, 5]
Expand All @@ -33,48 +34,46 @@ function createData(nSamples: number) {
yAxis,
nSamples
}
const data = syncSamplerInterval(samplerParams)
let data
if (async) {
data = await asyncSamplerInterval(samplerParams)
} else {
data = syncSamplerInterval(samplerParams)
}
return { data, xScale, yScale }
}

function compileAndEval() {
const compileAndEval = new Benchmark.Suite()
async function compileAndEval() {
const bench = new Bench()
const nSamples = 1000
compileAndEval
.add(`compile and eval ${nSamples}`, function () {
createData(nSamples)
})
// add listeners
.on('cycle', function (event) {
console.log(String(event.target))
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'))
})
.run({ async: false })
globals.workerPool = new IntervalWorkerPool(8)
bench.add(`compile and eval ${nSamples}`, async function () {
await createData(nSamples, false)
})
bench.add(`async compile and eval ${nSamples}`, async function () {
await createData(nSamples, true)
})

await bench.run()
console.table(bench.table())
}

function drawPath() {
const compileAndEval = new Benchmark.Suite()
async function drawPath() {
const bench = new Bench()
const nSamples = 1000
const { xScale, yScale, data } = createData(nSamples)
compileAndEval
.add(`drawPath ${nSamples}`, function () {
createPathD(xScale, yScale, 1 /* minWidthHeight, dummy = 1 */, data[0], false /* closed */)
})
// add listeners
.on('cycle', function (event) {
console.log(String(event.target))
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'))
})
.run({ async: false })
const { xScale, yScale, data } = await createData(nSamples, false)
bench.add(`drawPath ${nSamples}`, function () {
createPathD(xScale, yScale, 1 /* minWidthHeight, dummy = 1 */, data[0], false /* closed */)
})

await bench.run()
console.table(bench.table())
}

function main() {
compileAndEval()
drawPath()
async function main() {
await compileAndEval()
await drawPath()
await globals.workerPool.terminate()
}

main()
6 changes: 3 additions & 3 deletions src/samplers/builtIn.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import utils from '../utils'
import { builtIn as evaluate } from '../helpers/eval'
import { builtIn as evaluate } from '../helpers/eval.mjs'

import { FunctionPlotDatum, FunctionPlotScale } from '../types'
import { SamplerParams, SamplerFn } from './types'
Expand Down Expand Up @@ -28,7 +28,7 @@ function checkAsymptote(
const x0 = d0[0]
const x1 = d1[0]
const samples = utils.linspace(x0, x1, n)
let oldY, oldX
let oldY: number, oldX: number
for (let i = 0; i < n; i += 1) {
const x = samples[i]
const y = evaluate(d, 'fn', { x })
Expand All @@ -51,7 +51,7 @@ function checkAsymptote(
* through the process of detecting slope/sign brusque changes
*/
function split(d: FunctionPlotDatum, data: SamplerResultGroup, yScale: FunctionPlotScale): SamplerResult {
let oldSign
let oldSign: number
const samplerResult: SamplerResult = []
const yMin = yScale.domain()[0] - utils.infinity()
const yMax = yScale.domain()[1] + utils.infinity()
Expand Down
2 changes: 1 addition & 1 deletion src/samplers/interval.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import intervalArithmeticEval, { Interval } from 'interval-arithmetic-eval'

import { interval as evaluate } from '../helpers/eval'
import { interval as evaluate } from '../helpers/eval.mjs'
import utils from '../utils'
import globals from '../globals'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-restricted-globals */
import { interval } from '../helpers/eval'
import { interval } from '../helpers/eval.mjs'

self.onmessage = ({ data }) => {
const d = data.d
Expand Down
Loading

0 comments on commit 7bcd588

Please sign in to comment.