Skip to content

Commit be4648c

Browse files
authored
refactor: lazy initialize caches (#156)
1 parent 2541a1e commit be4648c

File tree

8 files changed

+1501
-1154
lines changed

8 files changed

+1501
-1154
lines changed

.changeset/neat-rings-joke.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"synckit": patch
3+
---
4+
5+
refactor: lazy initialize caches

benchmarks/benchmark.cjs

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ class Benchmark {
8181
return a === b
8282
? 'same'
8383
: a > b
84-
? (a / b).toFixed(2) + 'x slower'
85-
: (b / a).toFixed(2) + 'x faster'
84+
? (a / b).toFixed(2) + 'x slower'
85+
: (b / a).toFixed(2) + 'x faster'
8686
}
8787
}
8888

benchmarks/benchmark.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ class Benchmark {
8686
return a === b
8787
? 'same'
8888
: a > b
89-
? (a / b).toFixed(2) + 'x slower'
90-
: (b / a).toFixed(2) + 'x faster'
89+
? (a / b).toFixed(2) + 'x slower'
90+
: (b / a).toFixed(2) + 'x faster'
9191
}
9292
}
9393

package.json

+7-8
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
"tslib": "^2.6.2"
5757
},
5858
"devDependencies": {
59-
"@1stg/lib-config": "^12.0.0",
59+
"@1stg/lib-config": "^13.0.0",
6060
"@changesets/changelog-github": "^0.5.0",
6161
"@changesets/cli": "^2.27.1",
6262
"@swc-node/register": "^1.6.8",
63-
"@types/jest": "^29.5.10",
64-
"@types/node": "^20.10.1",
63+
"@types/jest": "^29.5.11",
64+
"@types/node": "^20.10.6",
6565
"clean-pkg-json": "^1.2.0",
6666
"cross-env": "^7.0.3",
6767
"deasync": "^0.1.29",
@@ -73,14 +73,13 @@
7373
"sync-threads": "^1.0.1",
7474
"ts-expect": "^1.3.0",
7575
"ts-jest": "^29.1.1",
76-
"ts-node": "^10.9.1",
77-
"tsx": "^4.6.1",
78-
"type-coverage": "^2.27.0",
79-
"typescript": "^5.3.2",
76+
"ts-node": "^10.9.2",
77+
"tsx": "^4.7.0",
78+
"type-coverage": "^2.27.1",
79+
"typescript": "^5.3.3",
8080
"yarn-deduplicate": "^6.0.2"
8181
},
8282
"resolutions": {
83-
"prettier": "^2.8.8",
8483
"synckit": "link:."
8584
},
8685
"commitlint": {

src/index.ts

+33-23
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ export const TsRunner = {
4646
export type TsRunner = ValueOf<typeof TsRunner>
4747

4848
const {
49-
SYNCKIT_TIMEOUT,
49+
NODE_OPTIONS,
5050
SYNCKIT_EXEC_ARGV,
51-
SYNCKIT_TS_RUNNER,
5251
SYNCKIT_GLOBAL_SHIMS,
53-
NODE_OPTIONS,
52+
SYNCKIT_TIMEOUT,
53+
SYNCKIT_TS_RUNNER,
5454
} = process.env
5555

5656
export const DEFAULT_TIMEOUT = SYNCKIT_TIMEOUT ? +SYNCKIT_TIMEOUT : undefined
@@ -78,14 +78,14 @@ export const DEFAULT_GLOBAL_SHIMS_PRESET: GlobalShim[] = [
7878

7979
export const MTS_SUPPORTED_NODE_VERSION = 16
8080

81-
const syncFnCache = new Map<string, AnyFn>()
81+
let syncFnCache: Map<string, AnyFn> | undefined
8282

8383
export interface SynckitOptions {
84-
timeout?: number
8584
execArgv?: string[]
86-
tsRunner?: TsRunner
87-
transferList?: TransferListItem[]
8885
globalShims?: GlobalShim[] | boolean
86+
timeout?: number
87+
transferList?: TransferListItem[]
88+
tsRunner?: TsRunner
8989
}
9090

9191
// MessagePort doesn't copy the properties of Error objects. We still want
@@ -107,16 +107,18 @@ export function createSyncFn<T extends AnyAsyncFn<R>, R = unknown>(
107107
workerPath: string,
108108
timeoutOrOptions?: SynckitOptions | number,
109109
): Syncify<T> {
110-
if (!path.isAbsolute(workerPath)) {
111-
throw new Error('`workerPath` must be absolute')
112-
}
110+
syncFnCache ??= new Map()
113111

114112
const cachedSyncFn = syncFnCache.get(workerPath)
115113

116114
if (cachedSyncFn) {
117115
return cachedSyncFn as Syncify<T>
118116
}
119117

118+
if (!path.isAbsolute(workerPath)) {
119+
throw new Error('`workerPath` must be absolute')
120+
}
121+
120122
const syncFn = startWorkerThread<R, T>(
121123
workerPath,
122124
/* istanbul ignore next */ typeof timeoutOrOptions === 'number'
@@ -309,8 +311,8 @@ export const encodeImportModule = (
309311
(named === null
310312
? '* as ' + globalName
311313
: named?.trim()
312-
? `{${named}}`
313-
: globalName) +
314+
? `{${named}}`
315+
: globalName) +
314316
' from'
315317
: ''
316318
} '${
@@ -354,7 +356,7 @@ export const _generateGlobals = (
354356
'',
355357
)
356358

357-
const globalsCache = new Map<string, [content: string, filepath?: string]>()
359+
let globalsCache: Map<string, [content: string, filepath?: string]> | undefined
358360

359361
let tmpdir: string
360362

@@ -371,6 +373,8 @@ export const generateGlobals = (
371373
globalShims: GlobalShim[],
372374
type: 'import' | 'require' = 'import',
373375
) => {
376+
globalsCache ??= new Map()
377+
374378
const cached = globalsCache.get(workerPath)
375379

376380
if (cached) {
@@ -462,14 +466,17 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
462466
globalShims === true
463467
? DEFAULT_GLOBAL_SHIMS_PRESET
464468
: Array.isArray(globalShims)
465-
? globalShims
466-
: []
469+
? globalShims
470+
: []
467471
).filter(({ moduleName }) => isPkgAvailable(moduleName))
468472

469473
// We store a single Byte in the SharedArrayBuffer
470474
// for the notification, we can used a fixed size
471-
sharedBuffer ??= new SharedArrayBuffer(INT32_BYTES)
472-
sharedBufferView ??= new Int32Array(sharedBuffer, 0, 1)
475+
sharedBufferView ??= new Int32Array(
476+
(sharedBuffer ??= new SharedArrayBuffer(INT32_BYTES)),
477+
0,
478+
1,
479+
)
473480

474481
const useGlobals = finalGlobalShims.length > 0
475482

@@ -484,12 +491,12 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
484491
)};import '${String(workerPathUrl)}'`,
485492
)
486493
: useEval
487-
? `${generateGlobals(
488-
finalWorkerPath,
489-
finalGlobalShims,
490-
'require',
491-
)};${encodeImportModule(finalWorkerPath, 'require')}`
492-
: workerPathUrl,
494+
? `${generateGlobals(
495+
finalWorkerPath,
496+
finalGlobalShims,
497+
'require',
498+
)};${encodeImportModule(finalWorkerPath, 'require')}`
499+
: workerPathUrl,
493500
{
494501
eval: useEval,
495502
workerData: { sharedBuffer, workerPort },
@@ -504,9 +511,11 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
504511
const id = nextID++
505512

506513
const msg: MainToWorkerMessage<Parameters<T>> = { id, args }
514+
507515
worker.postMessage(msg)
508516

509517
const status = Atomics.wait(sharedBufferView!, 0, 0, timeout)
518+
510519
// Reset SharedArrayBuffer for next call
511520
Atomics.store(sharedBufferView!, 0, 0)
512521

@@ -551,6 +560,7 @@ export function runAsWorker<
551560
}
552561

553562
const { workerPort, sharedBuffer } = workerData as WorkerData
563+
554564
const sharedBufferView = new Int32Array(sharedBuffer, 0, 1)
555565

556566
parentPort!.on(

test/ts-runner.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ test('unknown ts runner', async () => {
135135

136136
expect(() =>
137137
createSyncFn<AsyncWorkerFn>(path.resolve(_dirname, 'worker.js'), {
138-
// @ts-expect-error
138+
// @ts-expect-error -- intended
139139
tsRunner: 'unknown',
140140
}),
141141
).toThrowErrorMatchingInlineSnapshot(`"Unknown ts runner: unknown"`)

test/types-d.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Syncify,
99
} from 'synckit'
1010

11-
// @ts-expect-error
11+
// @ts-expect-error -- intended
1212
expectType<Syncify<() => 1>>(true)
1313

1414
expectType<TypeEqual<Syncify<() => Promise<true>>, () => true>>(true)
@@ -24,15 +24,15 @@ expectType<() => 1>(createSyncFn<() => Promise<1>>(''))
2424
expectType<() => true>(createSyncFn<() => Promise<true>>(''))
2525
expectType<() => true>(createSyncFn<() => Promise<never>>(''))
2626

27-
// @ts-expect-error
27+
// @ts-expect-error -- intended
2828
createSyncFn<() => 0>('')
2929

3030
expectType<void>(runAsWorker(() => Promise.resolve(1)))
3131

32-
// @ts-expect-error
32+
// @ts-expect-error -- intended
3333
runAsWorker(() => 1)
3434

3535
runAsWorker<() => Promise<string>>(() =>
36-
// @ts-expect-error
36+
// @ts-expect-error -- intended
3737
Promise.resolve(1),
3838
)

0 commit comments

Comments
 (0)