Skip to content

Commit

Permalink
Move web-workers to be a dev-dependency and not used in the prod bundle
Browse files Browse the repository at this point in the history
Webpack is doing a transformation of the statement `new Worker(...)`
which means that we can't use new MyWorker() because it confuses it.

Because the statement can't be changed, we can set global.Window and
override the value of it depending on the IntervalWorkerPool
constructors values.
  • Loading branch information
mauriciopoppe committed Oct 26, 2024
1 parent a9d536a commit 44e2265
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 38 deletions.
11 changes: 6 additions & 5 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@
"d3-shape": "^3.1.0",
"d3-zoom": "^3.0.0",
"events": "^3.3.0",
"interval-arithmetic-eval": "^0.5.1",
"web-worker": "^1.2.0"
"interval-arithmetic-eval": "^0.5.1"
},
"devDependencies": {
"@babel/core": "^7.19.1",
Expand Down Expand Up @@ -117,6 +116,7 @@
"tsx": "^4.6.2",
"typedoc": "^0.23.15",
"typescript": "^4.8.3",
"web-worker": "^1.3.0",
"webpack": "^5.86.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.11.0"
Expand Down
5 changes: 4 additions & 1 deletion site/jest-function-plot.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<!-- This page is used for tests purposes, think twice before making changes in <body> -->
<!--
This page is referenced from the e2e tests
before making changes in <body> please read test/e2e/graphs.test.ts
-->
<!doctype html>
<html>
<head lang="en">
Expand Down
44 changes: 21 additions & 23 deletions site/playground.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,32 @@
<script src="./function-plot.js"></script>
<script>
functionPlot.withWebWorkers(8)
// functionPlot({
// target: '#playground',
// width: window.innerWidth,
// height: window.innerHeight,
// data: [
// { fn: 'x^2', nSamples: 4000, sampler: 'asyncInterval' },
// { fn: 'sin(x)', nSamples: 4000, sampler: 'asyncInterval' },
// { fn: '1/x', nSamples: 4000, sampler: 'asyncInterval' },
// ]
// })
functionPlot({
target: '#playground',
data: [
{
fn: '-sqrt(-x)',
nSamples: 100,
graphType: 'scatter'
},
{
fn: 'sqrt(x)',
graphType: 'polyline'
},
{
fn: 'x^2',
graphType: 'interval'
}
{ fn: 'x^2', nSamples: 4000, sampler: 'asyncInterval' },
{ fn: 'sin(x)', nSamples: 4000, sampler: 'asyncInterval' },
{ fn: '1/x', nSamples: 4000, sampler: 'asyncInterval' }
]
})
// functionPlot({
// target: '#playground',
// data: [
// {
// fn: '-sqrt(-x)',
// nSamples: 100,
// graphType: 'scatter'
// },
// {
// fn: 'sqrt(x)',
// graphType: 'polyline'
// },
// {
// fn: 'x^2',
// graphType: 'interval'
// }
// ]
// })
</script>
</body>
</html>
5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ registerGraphType('interval', interval)
registerGraphType('scatter', scatter)
registerGraphType('text', text)

// Web workers initializer.
function withWebWorkers(nWorkers = 8, publicPath = window.location.href) {
function withWebWorkers(nWorkers = 8, WorkerConstructor = window.Worker, publicPath = window.location.href) {
// @ts-ignore
window.__webpack_public_path__ = publicPath
globals.workerPool = new IntervalWorkerPool(nWorkers)
globals.workerPool = new IntervalWorkerPool(nWorkers, WorkerConstructor)
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/perf/interval-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { Bench } from 'tinybench'
import { scaleLinear } from 'd3-scale'
import Worker from 'web-worker'

import globals from '../globals.mjs'
import { IntervalWorkerPool, BackpressureStrategy } from '../samplers/interval_worker_pool.js'
Expand Down Expand Up @@ -111,7 +112,7 @@ async function drawPath() {
}

async function main() {
globals.workerPool = new IntervalWorkerPool(8)
globals.workerPool = new IntervalWorkerPool(8, Worker.default)
await compileAndEval()
await consecutiveEval()
await drawPath()
Expand Down
20 changes: 17 additions & 3 deletions src/samplers/interval_worker_pool.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import Worker from 'web-worker'

import { FunctionPlotDatum } from '../types.js'

// Webpack is doing a transformation of the statement `new Worker(...)`
// which means that we can't use new MyWorker() because it confuses it.
//
// Because the statement can't be changed, we can set global.Window and
// override the value of it depending on the IntervalWorkerPool constructors values.
if (typeof window === 'undefined') {
global.Worker = null
}

interface IntervalTask {
d: FunctionPlotDatum
lo: number
Expand Down Expand Up @@ -42,7 +49,7 @@ export class IntervalWorkerPool {
private nTasks: number
private backpressure: BackpressureStrategy

constructor(nThreads: number) {
constructor(nThreads: number, MyWorker: any) {
this.nTasks = 0
this.idleWorkers = []
this.tasks = []
Expand All @@ -51,6 +58,13 @@ export class IntervalWorkerPool {
this.backpressure = BackpressureStrategy.InvalidateSeenScan
this.taskIdToIdx = new Map()

// Webpack is doing a transformation of the statement `new Worker(...)`
// which means that we can't use new MyWorker() because it confuses it.
//
// A workaround is to override Worker with MyWorker
// - In the browser MyWorker is window.Worker
// - In the server it's web-worker's impl for node (worker_threads)
Worker = MyWorker
for (let i = 0; i < nThreads; i += 1) {
// NOTE: new URL(...) cannot be a variable!
// This is a requirement for the webpack worker loader
Expand Down

0 comments on commit 44e2265

Please sign in to comment.