Skip to content

Commit

Permalink
refactor: lazy initialize caches (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Jan 4, 2024
1 parent 2541a1e commit be4648c
Show file tree
Hide file tree
Showing 8 changed files with 1,501 additions and 1,154 deletions.
5 changes: 5 additions & 0 deletions .changeset/neat-rings-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"synckit": patch
---

refactor: lazy initialize caches
4 changes: 2 additions & 2 deletions benchmarks/benchmark.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class Benchmark {
return a === b
? 'same'
: a > b
? (a / b).toFixed(2) + 'x slower'
: (b / a).toFixed(2) + 'x faster'
? (a / b).toFixed(2) + 'x slower'
: (b / a).toFixed(2) + 'x faster'
}
}

Expand Down
4 changes: 2 additions & 2 deletions benchmarks/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class Benchmark {
return a === b
? 'same'
: a > b
? (a / b).toFixed(2) + 'x slower'
: (b / a).toFixed(2) + 'x faster'
? (a / b).toFixed(2) + 'x slower'
: (b / a).toFixed(2) + 'x faster'
}
}

Expand Down
15 changes: 7 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@
"tslib": "^2.6.2"
},
"devDependencies": {
"@1stg/lib-config": "^12.0.0",
"@1stg/lib-config": "^13.0.0",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.1",
"@swc-node/register": "^1.6.8",
"@types/jest": "^29.5.10",
"@types/node": "^20.10.1",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.6",
"clean-pkg-json": "^1.2.0",
"cross-env": "^7.0.3",
"deasync": "^0.1.29",
Expand All @@ -73,14 +73,13 @@
"sync-threads": "^1.0.1",
"ts-expect": "^1.3.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsx": "^4.6.1",
"type-coverage": "^2.27.0",
"typescript": "^5.3.2",
"ts-node": "^10.9.2",
"tsx": "^4.7.0",
"type-coverage": "^2.27.1",
"typescript": "^5.3.3",
"yarn-deduplicate": "^6.0.2"
},
"resolutions": {
"prettier": "^2.8.8",
"synckit": "link:."
},
"commitlint": {
Expand Down
56 changes: 33 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ export const TsRunner = {
export type TsRunner = ValueOf<typeof TsRunner>

const {
SYNCKIT_TIMEOUT,
NODE_OPTIONS,
SYNCKIT_EXEC_ARGV,
SYNCKIT_TS_RUNNER,
SYNCKIT_GLOBAL_SHIMS,
NODE_OPTIONS,
SYNCKIT_TIMEOUT,
SYNCKIT_TS_RUNNER,
} = process.env

export const DEFAULT_TIMEOUT = SYNCKIT_TIMEOUT ? +SYNCKIT_TIMEOUT : undefined
Expand Down Expand Up @@ -78,14 +78,14 @@ export const DEFAULT_GLOBAL_SHIMS_PRESET: GlobalShim[] = [

export const MTS_SUPPORTED_NODE_VERSION = 16

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

export interface SynckitOptions {
timeout?: number
execArgv?: string[]
tsRunner?: TsRunner
transferList?: TransferListItem[]
globalShims?: GlobalShim[] | boolean
timeout?: number
transferList?: TransferListItem[]
tsRunner?: TsRunner
}

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

const cachedSyncFn = syncFnCache.get(workerPath)

if (cachedSyncFn) {
return cachedSyncFn as Syncify<T>
}

if (!path.isAbsolute(workerPath)) {
throw new Error('`workerPath` must be absolute')
}

const syncFn = startWorkerThread<R, T>(
workerPath,
/* istanbul ignore next */ typeof timeoutOrOptions === 'number'
Expand Down Expand Up @@ -309,8 +311,8 @@ export const encodeImportModule = (
(named === null
? '* as ' + globalName
: named?.trim()
? `{${named}}`
: globalName) +
? `{${named}}`
: globalName) +
' from'
: ''
} '${
Expand Down Expand Up @@ -354,7 +356,7 @@ export const _generateGlobals = (
'',
)

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

let tmpdir: string

Expand All @@ -371,6 +373,8 @@ export const generateGlobals = (
globalShims: GlobalShim[],
type: 'import' | 'require' = 'import',
) => {
globalsCache ??= new Map()

const cached = globalsCache.get(workerPath)

if (cached) {
Expand Down Expand Up @@ -462,14 +466,17 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
globalShims === true
? DEFAULT_GLOBAL_SHIMS_PRESET
: Array.isArray(globalShims)
? globalShims
: []
? globalShims
: []
).filter(({ moduleName }) => isPkgAvailable(moduleName))

// We store a single Byte in the SharedArrayBuffer
// for the notification, we can used a fixed size
sharedBuffer ??= new SharedArrayBuffer(INT32_BYTES)
sharedBufferView ??= new Int32Array(sharedBuffer, 0, 1)
sharedBufferView ??= new Int32Array(
(sharedBuffer ??= new SharedArrayBuffer(INT32_BYTES)),
0,
1,
)

const useGlobals = finalGlobalShims.length > 0

Expand All @@ -484,12 +491,12 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
)};import '${String(workerPathUrl)}'`,
)
: useEval
? `${generateGlobals(
finalWorkerPath,
finalGlobalShims,
'require',
)};${encodeImportModule(finalWorkerPath, 'require')}`
: workerPathUrl,
? `${generateGlobals(
finalWorkerPath,
finalGlobalShims,
'require',
)};${encodeImportModule(finalWorkerPath, 'require')}`
: workerPathUrl,
{
eval: useEval,
workerData: { sharedBuffer, workerPort },
Expand All @@ -504,9 +511,11 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
const id = nextID++

const msg: MainToWorkerMessage<Parameters<T>> = { id, args }

worker.postMessage(msg)

const status = Atomics.wait(sharedBufferView!, 0, 0, timeout)

// Reset SharedArrayBuffer for next call
Atomics.store(sharedBufferView!, 0, 0)

Expand Down Expand Up @@ -551,6 +560,7 @@ export function runAsWorker<
}

const { workerPort, sharedBuffer } = workerData as WorkerData

const sharedBufferView = new Int32Array(sharedBuffer, 0, 1)

parentPort!.on(
Expand Down
2 changes: 1 addition & 1 deletion test/ts-runner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ test('unknown ts runner', async () => {

expect(() =>
createSyncFn<AsyncWorkerFn>(path.resolve(_dirname, 'worker.js'), {
// @ts-expect-error
// @ts-expect-error -- intended
tsRunner: 'unknown',
}),
).toThrowErrorMatchingInlineSnapshot(`"Unknown ts runner: unknown"`)
Expand Down
8 changes: 4 additions & 4 deletions test/types-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Syncify,
} from 'synckit'

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

expectType<TypeEqual<Syncify<() => Promise<true>>, () => true>>(true)
Expand All @@ -24,15 +24,15 @@ expectType<() => 1>(createSyncFn<() => Promise<1>>(''))
expectType<() => true>(createSyncFn<() => Promise<true>>(''))
expectType<() => true>(createSyncFn<() => Promise<never>>(''))

// @ts-expect-error
// @ts-expect-error -- intended
createSyncFn<() => 0>('')

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

// @ts-expect-error
// @ts-expect-error -- intended
runAsWorker(() => 1)

runAsWorker<() => Promise<string>>(() =>
// @ts-expect-error
// @ts-expect-error -- intended
Promise.resolve(1),
)

0 comments on commit be4648c

Please sign in to comment.