mirror of https://github.com/vuejs/vitepress
parent
ba0c3f5969
commit
6f3d80e73c
@ -1,88 +0,0 @@
|
|||||||
import { Worker, workerData, isMainThread, parentPort } from 'worker_threads'
|
|
||||||
import { type UpdateHandle } from '../utils/task'
|
|
||||||
import { type RenderPageContext } from './render'
|
|
||||||
|
|
||||||
type TaskAllocator<T> = () => Promise<T | undefined>
|
|
||||||
|
|
||||||
import RpcContext from 'rpc-magic-proxy'
|
|
||||||
|
|
||||||
export default async function cluster(
|
|
||||||
entryPath: string,
|
|
||||||
context: RenderPageContext,
|
|
||||||
pages: string[],
|
|
||||||
update: UpdateHandle
|
|
||||||
) {
|
|
||||||
// - Each render worker could consume up to 150% of a CPU core.
|
|
||||||
// - One extra core is allocated to the main thread.
|
|
||||||
// - Excess worker will cause too much RPC workload for main thread,
|
|
||||||
// therefore harm the overall performance.
|
|
||||||
const concurrency = Math.round(
|
|
||||||
Math.max((context.config.concurrency - 1) / 1.5, 1)
|
|
||||||
)
|
|
||||||
|
|
||||||
const num_tasks = pages.length
|
|
||||||
|
|
||||||
const pageAlloc: TaskAllocator<string> = async () => {
|
|
||||||
const page = pages.shift()
|
|
||||||
if (page) update(num_tasks - pages.length, num_tasks)
|
|
||||||
return page
|
|
||||||
}
|
|
||||||
|
|
||||||
const tasks = []
|
|
||||||
|
|
||||||
const ctx = new RpcContext()
|
|
||||||
const workerData = await ctx.serialize({
|
|
||||||
concurrency,
|
|
||||||
entryPath,
|
|
||||||
pageAlloc,
|
|
||||||
context,
|
|
||||||
workload: 'render'
|
|
||||||
})
|
|
||||||
|
|
||||||
for (let _ = 0; _ < concurrency; _++) {
|
|
||||||
const worker = new Worker(new URL(import.meta.url), { workerData })
|
|
||||||
ctx.bind(worker)
|
|
||||||
tasks.push(
|
|
||||||
new Promise((res, rej) =>
|
|
||||||
worker.once('exit', (code) => {
|
|
||||||
if (code === 0) res(code)
|
|
||||||
else rej()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(tasks)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function renderWorker() {
|
|
||||||
const ctx = new RpcContext(parentPort!)
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
entryPath,
|
|
||||||
pageAlloc,
|
|
||||||
context
|
|
||||||
}: {
|
|
||||||
entryPath: string
|
|
||||||
pageAlloc: TaskAllocator<string>
|
|
||||||
context: RenderPageContext
|
|
||||||
} = ctx.deserialize(workerData)
|
|
||||||
const { renderPage } = await import('./render')
|
|
||||||
const { render } = await import(entryPath)
|
|
||||||
async function executor() {
|
|
||||||
while (true) {
|
|
||||||
const page = await pageAlloc()
|
|
||||||
if (!page) break
|
|
||||||
await renderPage(render, page, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const concurrency = Math.max(context.config.concurrency, 1)
|
|
||||||
await Promise.all(Array.from({ length: concurrency }, () => executor()))
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
} finally {
|
|
||||||
ctx.reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isMainThread && workerData?.workload === 'render') renderWorker()
|
|
Loading…
Reference in new issue