perf: allow a thread for each output encoding format
This commit is contained in:
parent
76c9782845
commit
bd7824e8b8
1 changed files with 60 additions and 28 deletions
|
@ -1,4 +1,4 @@
|
|||
|
||||
import { cpus } from 'os'
|
||||
import { isMainThread } from 'node:worker_threads';
|
||||
import WorkerPool from '../../utils/workerPool.js';
|
||||
import * as impl from './impl.js';
|
||||
|
@ -16,9 +16,15 @@ type ResizeOperation = {
|
|||
}
|
||||
export type Operation = RotateOperation | ResizeOperation
|
||||
|
||||
// HACK! Find the right import assuming this works
|
||||
const getWorker = execOnce(
|
||||
() => new WorkerPool(6, './node_modules/@astrojs/image/dist/vendor/squoosh/image-pool.js')
|
||||
() => {
|
||||
return new WorkerPool(
|
||||
// There will be at most 7 workers needed since each worker will take
|
||||
// at least 1 operation type.
|
||||
Math.max(1, Math.min(cpus().length - 1, 7)),
|
||||
'./node_modules/@astrojs/image/dist/vendor/squoosh/image-pool.js'
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
type DecodeParams = {
|
||||
|
@ -36,13 +42,26 @@ type RotateParams = {
|
|||
imageData: ImageData,
|
||||
numRotations: number
|
||||
};
|
||||
type EncodeParams = {
|
||||
operation: 'encode',
|
||||
type EncodeAvifParams = {
|
||||
operation: 'encodeavif',
|
||||
imageData: ImageData,
|
||||
format: OutputFormat,
|
||||
quality?: number
|
||||
quality: number
|
||||
}
|
||||
type JobMessage = DecodeParams | ResizeParams | RotateParams | EncodeParams
|
||||
type EncodeJpegParams = {
|
||||
operation: 'encodejpeg',
|
||||
imageData: ImageData,
|
||||
quality: number
|
||||
}
|
||||
type EncodePngParams = {
|
||||
operation: 'encodepng',
|
||||
imageData: ImageData
|
||||
}
|
||||
type EncodeWebpParams = {
|
||||
operation: 'encodewebp',
|
||||
imageData: ImageData,
|
||||
quality: number
|
||||
}
|
||||
type JobMessage = DecodeParams | ResizeParams | RotateParams | EncodeAvifParams | EncodeJpegParams | EncodePngParams | EncodeWebpParams
|
||||
|
||||
function handleJob(params: JobMessage) {
|
||||
switch (params.operation) {
|
||||
|
@ -52,20 +71,14 @@ function handleJob(params: JobMessage) {
|
|||
return impl.resize({ image: params.imageData as any, width: params.width, height: params.height })
|
||||
case 'rotate':
|
||||
return impl.rotate(params.imageData as any, params.numRotations);
|
||||
case 'encode':
|
||||
switch (params.format) {
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
return impl.encodeJpeg(params.imageData as any, { quality: params.quality || 100 })
|
||||
case 'webp':
|
||||
return impl.encodeWebp(params.imageData as any, { quality: params.quality || 100 })
|
||||
case 'avif':
|
||||
return impl.encodeAvif(params.imageData as any, { quality: params.quality || 100 })
|
||||
case 'png':
|
||||
return impl.encodePng(params.imageData as any)
|
||||
default:
|
||||
throw Error(`Unsupported encoding format`)
|
||||
}
|
||||
case 'encodeavif':
|
||||
return impl.encodeAvif(params.imageData as any, { quality: params.quality })
|
||||
case 'encodejpeg':
|
||||
return impl.encodeJpeg(params.imageData as any, { quality: params.quality })
|
||||
case 'encodepng':
|
||||
return impl.encodePng(params.imageData as any)
|
||||
case 'encodewebp':
|
||||
return impl.encodeWebp(params.imageData as any, { quality: params.quality })
|
||||
default:
|
||||
throw Error(`Invalid job "${(params as any).operation}"`);
|
||||
}
|
||||
|
@ -77,6 +90,7 @@ export async function processBuffer(
|
|||
encoding: OutputFormat,
|
||||
quality: number
|
||||
): Promise<Buffer> {
|
||||
// @ts-ignore
|
||||
const worker = await getWorker()
|
||||
|
||||
let imageData = await worker.dispatchJob({
|
||||
|
@ -100,12 +114,30 @@ export async function processBuffer(
|
|||
}
|
||||
}
|
||||
|
||||
return await worker.dispatchJob({
|
||||
operation: 'encode',
|
||||
format: encoding,
|
||||
imageData,
|
||||
quality
|
||||
}) as Buffer
|
||||
switch (encoding) {
|
||||
case 'avif':
|
||||
return await worker.dispatchJob({ operation: 'encodeavif', imageData, quality: quality || 100 }) as Buffer;
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
return await worker.dispatchJob({
|
||||
operation: 'encodejpeg',
|
||||
imageData,
|
||||
quality: quality || 100,
|
||||
}) as Buffer;
|
||||
case 'png':
|
||||
return await worker.dispatchJob({
|
||||
operation: 'encodepng',
|
||||
imageData,
|
||||
}) as Buffer;
|
||||
case 'webp':
|
||||
return await worker.dispatchJob({
|
||||
operation: 'encodejpeg',
|
||||
imageData,
|
||||
quality: quality || 100,
|
||||
}) as Buffer;
|
||||
default:
|
||||
throw Error(`Unsupported encoding format`)
|
||||
}
|
||||
}
|
||||
|
||||
if (!isMainThread) {
|
||||
|
|
Loading…
Reference in a new issue