Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: lazy initialize caches #156

Merged
merged 2 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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),
)
Loading
Loading