### Install Dependencies Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/n-api.mdx Run this command to install the necessary dependencies for the native addon example. ```bash npm i ``` -------------------------------- ### Running the Server Examples Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/react-ssr.mdx Commands to run the pooled and unpooled Fastify server examples using Node.js. ```bash node pooled.js ``` ```bash node unpooled.js ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/piscinajs/piscina/blob/current/docs/README.md Installs all necessary packages for the project. Run this command in the project's root directory. ```bash $ npm i ``` -------------------------------- ### Install Autocannon Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Install the benchmarking tool globally to test server performance. ```console $ npm i -g autocannon ``` -------------------------------- ### Run Async Unpooled Server Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Start the unpooled async server variant. ```console $ node async-sleep-unpooled ``` -------------------------------- ### Scrypt Example package.json Scripts (JSON) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/scrypt.mdx Defines npm scripts for running different scrypt implementations (pooled, unpooled, sync, async) with a monitor. This JSON file is used to manage and execute the scrypt examples. ```json { "name": "scrypt", "version": "1.0.0", "scripts": { "pooled": "node -r ./monitor pooled", "unpooled": "node -r ./monitor unpooled", "pooled-sync": "node -r ./monitor pooled_sync", "unpooled-sync": "node -r ./monitor unpooled_sync" }, "keywords": [], "author": "", "license": "MIT", "description": "" } ``` ```json { "name": "scrypt", "version": "1.0.0", "scripts": { "pooled": "ts-node -r ./monitor pooled", "unpooled": "ts-node -r ./monitor unpooled", "pooled-sync": "ts-node -r ./monitor pooled_sync", "unpooled-sync": "ts-node -r ./monitor unpooled_sync" }, "keywords": [], "author": "", "license": "MIT", "description": "", "dependencies": { "@types/node": "^20.14.10", "ts-node": "^10.9.2", "typescript": "^5.5.3" } } ``` -------------------------------- ### Run pooled synchronous sleep server Source: https://github.com/piscinajs/piscina/blob/current/examples/server/README.md Execute the pooled synchronous sleep server example. ```console $ node sync-sleep-pooled ``` -------------------------------- ### Run Pooled Sync Sleep Example Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Executes the sync-sleep-pooled example with specified concurrency and idle timeout parameters. ```console $ node sync-sleep-pooled 10 1000 ``` -------------------------------- ### Initialize Piscina and run a task Source: https://github.com/piscinajs/piscina/blob/current/README.md Basic setup for a Piscina pool in main.js and a corresponding worker.js file. ```javascript const path = require("path"); const Piscina = require("piscina"); const piscina = new Piscina({ filename: path.resolve(__dirname, "worker.js"), }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```javascript module.exports = ({ a, b }) => { return a + b; }; ``` -------------------------------- ### Start Local Development Server Source: https://github.com/piscinajs/piscina/blob/current/docs/README.md Starts a local development server that automatically refreshes the browser on code changes. This is useful for active development. ```bash $ npm run start ``` -------------------------------- ### Setup Main File (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx Create a Piscina instance pointing to your worker file and run a task. Ensure the worker file path is correctly resolved. ```javascript const path = require("path"); const Piscina = require("piscina"); // Create a new Piscina instance pointing to your worker file const piscina = new Piscina({ filename: path.resolve(__dirname, "worker.js"), }); // Run a task using Piscina (async () => { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // prints 10 })(); ``` -------------------------------- ### Implement custom load balancer Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/api-reference/class.md Example implementation of a least-busy load balancing strategy. ```js const { Piscina } = require('piscina'); function LeastBusyBalancer(opts) { const { maximumUsage } = opts; return (task, workers) => { let candidate = null; let checkpoint = maximumUsage; for (const worker of workers) { if (worker.currentUsage === 0) { candidate = worker; break; } if (worker.isRunningAbortableTask) continue; if (!task.isAbortable && worker.currentUsage < checkpoint) { candidate = worker; checkpoint = worker.currentUsage; } } return candidate; }; } const piscina = new Piscina({ loadBalancer: LeastBusyBalancer({ maximumUsage: 2 }), }); piscina .runTask({ filename: 'worker.js', name: 'default' }) .then((result) => console.log(result)) .catch((err) => console.error(err)); ``` ```ts import { Piscina } from 'piscina'; function LeastBusyBalancer( opts: LeastBusyBalancerOptions ): PiscinaLoadBalancer { const { maximumUsage } = opts; return (task, workers) => { let candidate: PiscinaWorker | null = null; let checkpoint = maximumUsage; for (const worker of workers) { if (worker.currentUsage === 0) { candidate = worker; break; } if (worker.isRunningAbortableTask) continue; if (!task.isAbortable && worker.currentUsage < checkpoint) { candidate = worker; checkpoint = worker.currentUsage; } } return candidate; }; } const piscina = new Piscina({ loadBalancer: LeastBusyBalancer({ maximumUsage: 2 }), }); piscina .runTask({ filename: 'worker.js', name: 'default' }) .then((result) => console.log(result)) .catch((err) => console.error(err)); ``` -------------------------------- ### Run Pooled Async Sleep Example Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Executes the async-sleep-pooled example with specified concurrency and idle timeout parameters. ```console $ node async-sleep-pooled 10 1000 ``` -------------------------------- ### Run Async Pooled Server Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Start the pooled async server variant using Piscina. ```console $ node async-sleep-pooled ``` -------------------------------- ### Benchmarking with Autocannon Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/react-ssr.mdx Instructions for installing and running `autocannon` to benchmark the performance of the pooled and unpooled server versions. ```bash npm i -g autocannon ``` ```bash autocannon http://localhost:3000 ``` -------------------------------- ### Install Progress Bar Dependency Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/progress.mdx Install the 'progress' npm package to enable progress bar functionality. ```bash npm install progress ``` -------------------------------- ### Install Piscina.js via package manager Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/Installation.mdx Use these commands to add the Piscina.js dependency to your project. ```bash npm install piscina ``` ```bash yarn add piscina ``` ```bash pnpm add piscina ``` ```bash bun add piscina ``` -------------------------------- ### Setup Main File (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx When using TypeScript, configure Piscina with a worker wrapper and provide worker data. The worker wrapper handles TypeScript compilation. ```javascript import Piscina from "piscina"; import { resolve } from "path"; import { filename } from "./worker"; const piscina = new Piscina({ filename: resolve(__dirname, "./workerWrapper.js"), workerData: { fullpath: filename }, }); (async () => { const result = await piscina.run({ a: 2, b: 3 }, { name: "addNumbers" }); console.log("Result:", result); })(); ``` -------------------------------- ### Run sync-sleep-unpooled server Source: https://github.com/piscinajs/piscina/blob/current/examples/server/README.md Starts the unpooled synchronous sleep server variant which blocks the event loop. ```console $ node sync-sleep-unpooled ``` -------------------------------- ### Using FixedQueue in JavaScript Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/advanced-topics/custom-task-queues.mdx Instantiate Piscina with the `FixedQueue` for improved performance. This example shows how to set up the pool and submit tasks. ```javascript const { Piscina, FixedQueue } = require("piscina"); const { resolve } = require("path"); // Create a Piscina pool with FixedQueue const piscina = new Piscina({ filename: resolve(__dirname, "worker.js"), taskQueue: new FixedQueue(), }); // Submit tasks to the pool for (let i = 0; i < 10; i++) { piscina .runTask({ data: i }) .then((result) => { console.log(result); }) .catch((error) => { console.error(error); }); } ``` -------------------------------- ### Javascript Simple Addition Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/simple.mdx Use this for a basic Javascript setup. Ensure the worker file is correctly resolved. ```javascript 'use strict'; const Piscina = require('../..'); const { resolve } = require('path'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js') }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```javascript 'use strict'; module.exports = ({ a, b }) => { return a + b; }; ``` -------------------------------- ### JavaScript BroadcastChannel Example Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/broadcast.mdx This example sets up a Piscina instance using BroadcastChannel for inter-thread communication. The main thread sends a message after a delay, which is then received by the worker threads. Ensure you are using Node.js v18+ for BroadcastChannel support. ```javascript 'use strict'; const { BroadcastChannel } = require('worker_threads'); const { resolve } = require('path'); const Piscina = require('piscina'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js'), atomics: 'disabled' }); async function main () { const bc = new BroadcastChannel('my_channel'); // start worker Promise.all([ piscina.run('thread 1'), piscina.run('thread 2') ]); // post message in one second setTimeout(() => { bc.postMessage('Main thread message'); }, 1000); } main(); ``` ```javascript 'use strict'; const { BroadcastChannel } = require('worker_threads'); module.exports = async (thread) => { const bc = new BroadcastChannel('my_channel'); bc.onmessage = (event) => { console.log(thread + ' Received from:' + event.data); }; await new Promise((resolve) => { setTimeout(resolve, 2000); }); }; ``` -------------------------------- ### ESM Main File Setup (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx Set up Piscina with ESM in a TypeScript project, using a worker wrapper and specifying the worker's filename. This ensures proper module resolution. ```javascript import { Piscina } from "piscina"; import { filename } from "./worker"; const workerWrapperURL = new URL("workerWrapper.js", import.meta.url); const piscina = new Piscina({ filename: workerWrapperURL.href, workerData: { fullpath: filename }, }); (async () => { const result = await piscina.run({ a: 4, b: 6 }, { name: "addNumbers" }); console.log(result); // Prints 10 })(); ``` -------------------------------- ### ESM Main File Setup Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx Configure Piscina to use ECMAScript Modules by providing a file:// URL for the worker. This is essential for modern JavaScript environments. ```javascript import { Piscina } from "piscina"; const piscina = new Piscina({ // The URL must be a file:// URL filename: new URL("./worker.mjs", import.meta.url).href, }); const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 ``` -------------------------------- ### Configure Worker Environment and Runtime Options Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/worker-options.mdx Set environment variables, command-line arguments, and execution arguments for worker threads. This example demonstrates passing custom env, argv, and execArgv to a worker, along with initial workerData. ```javascript 'use strict'; const Piscina = require('../..'); const { resolve } = require('path'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js'), env: { A: '123' }, argv: ['a', 'b', 'c'], execArgv: ['--no-warnings'], workerData: 'ABC' }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```javascript 'use strict'; const Piscina = require('../..'); const { format } = require('util'); module.exports = ({ a, b }) => { console.log( ` process.argv: ${process.argv.slice(2)} process.execArgv: ${process.execArgv} process.env: ${format({ ...process.env })} workerData: ${Piscina.workerData}`); return a + b; }; ``` -------------------------------- ### Typescript Simple Addition Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/simple.mdx This Typescript example demonstrates Piscina usage with worker data. Note the use of `workerWrapper.js` and `workerData` for passing file paths. ```typescript import Piscina from 'piscina'; import { resolve } from 'path'; import { filename } from './worker'; const piscina = new Piscina({ filename: resolve(__dirname, 'workerWrapper.js'), workerData: { fullpath: filename }, }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```typescript export const filename = __filename; interface AdditionParams { a: number; b: number; } export default ({ a, b }: AdditionParams): number => { return a + b; }; ``` -------------------------------- ### Configure thread priority with niceIncrement Source: https://github.com/piscinajs/piscina/blob/current/README.md Requires the @napi-rs/nice native addon to be installed. Higher values reduce CPU priority for worker threads. ```js const Piscina = require("piscina"); const pool = new Piscina({ worker: "/absolute/path/to/worker.js", niceIncrement: 20, }); ``` -------------------------------- ### Pooled React SSR with Fastify (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/react-ssr.mdx TypeScript version of the pooled setup. It configures `fastify-piscina` with a worker file and worker data, using `fastify.runTask()` for rendering. ```typescript import { resolve } from 'path'; import { filename } from './worker'; const fastify = require('fastify')(); fastify.register(require('fastify-piscina'), { filename: resolve(__dirname, 'workerWrapper.js'), workerData: { fullpath: filename }, execArgv: [], minThreads: 6, maxThreads: 6 }); // Declare a route fastify.get('/', async () => fastify.runTask({ name: 'James' }, { name: 'renderPage' })); // Run the server! const start = async () => { try { await fastify.listen({ port: 3000 }); } catch (err) { process.exit(1); } }; start(); process.on('SIGINT', () => { const waitTime = (fastify as any).piscina.waitTime; console.log('\nMax Queue Wait Time:', waitTime.max); console.log('Mean Queue Wait Time:', waitTime.mean); process.exit(0); }); ``` -------------------------------- ### Run Time Histogram Summary Source: https://github.com/piscinajs/piscina/blob/current/README.md Example of the object structure returned by the runTime property, providing statistical distribution of task execution times. ```js { average: 1880.25, mean: 1880.25, stddev: 1.93, min: 1877, max: 1882.0190887451172, p0_001: 1877, p0_01: 1877, p0_1: 1877, p1: 1877, p2_5: 1877, p10: 1877, p25: 1877, p50: 1881, p75: 1881, p90: 1882, p97_5: 1882, p99: 1882, p99_9: 1882, p99_99: 1882, p99_999: 1882 } ``` -------------------------------- ### Run Synchronous Scrypt with Piscina (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/scrypt.mdx This TypeScript script utilizes Piscina for synchronous scrypt operations, similar to the JavaScript example but with type safety. It requires a 'workerWrapper.js' file and assumes 'scrypt_sync.ts' is correctly set up. ```typescript 'use strict'; import Piscina from 'piscina'; import { resolve } from 'path'; import crypto from 'crypto'; import { promisify } from 'util'; import { filename } from './scrypt_sync'; const randomFill = promisify(crypto.randomFill); const { performance, PerformanceObserver } = require('perf_hooks'); const obs = new PerformanceObserver((entries: { getEntries: () => { duration: any; }[]; }) => { console.log(entries.getEntries()[0].duration); }); obs.observe({ entryTypes: ['measure'] }); const piscina = new Piscina({ filename: resolve(__dirname, 'workerWrapper.js'), workerData: { fullpath: filename }, }); process.on('exit', () => { const { runTime, waitTime } = piscina; console.log('Run Time Average:', runTime.average); console.log('Run Time Mean/Stddev:', runTime.mean, runTime.stddev); console.log('Run Time Min:', runTime.min); console.log('Run Time Max:', runTime.max); console.log('Wait Time Average:', waitTime.average); console.log('Wait Time Mean/Stddev:', waitTime.mean, waitTime.stddev); console.log('Wait Time Min:', waitTime.min); console.log('Wait Time Max:', waitTime.max); }); async function* generateInput() { let max = parseInt(process.argv[2] || '10', 10); const data = Buffer.allocUnsafe(10); while (max-- > 0) { yield randomFill(data); } } (async function () { performance.mark('start'); const keylen = 64; for await (const input of generateInput()) { await piscina.run({ input, keylen }); } performance.mark('end'); performance.measure('start to end', 'start', 'end'); })(); ``` ```typescript 'use strict'; import { scryptSync, randomFillSync } from 'crypto'; const salt = Buffer.allocUnsafe(16); export default function ({ input, keylen, N = 16384, r = 8, p = 1, maxmem = 32 * 1024 * 1024 }: { input: Buffer; keylen: number; N?: number; r?: number; p?: number; maxmem?: number; }): string { return scryptSync(input, randomFillSync(salt), keylen, { N, r, p, maxmem }).toString('hex'); } export const filename = __filename; ``` -------------------------------- ### Worker script for Task Queue Example (Javascript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/task-queue.mdx A simple worker script that simulates work by sleeping for 100ms, logs the task priority, and returns it. This helps in observing the task execution order based on priority. ```javascript 'use strict'; const { promisify } = require('util'); const sleep = promisify(setTimeout); module.exports = async ({ priority }) => { await sleep(100); process._rawDebug(`${priority}`); return priority; }; ``` -------------------------------- ### Configure Resource Limits in Main File (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/resource-limit.mdx Configure resource limits for worker threads using TypeScript. This example demonstrates setting memory constraints for workers, similar to the JavaScript version, and includes type annotations. ```typescript import Piscina from 'piscina'; import { resolve } from 'path'; import { strictEqual } from 'assert'; import { filename } from './worker'; const piscina = new Piscina({ filename: resolve(__dirname, 'workerWrapper.js'), workerData: { fullpath: filename }, resourceLimits: { maxOldGenerationSizeMb: 16, maxYoungGenerationSizeMb: 4, codeRangeSizeMb: 16 } }); (async function () { try { await piscina.run({}, { name: 'memoryLeak' }); } catch (err) { console.log('Worker terminated due to resource limits'); strictEqual((err as any).code, 'ERR_WORKER_OUT_OF_MEMORY'); } })(); ``` -------------------------------- ### Run Multiple Tasks from One File (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/multiple-workers-one-file.mdx Use `pool.run()` with an options object specifying the function name to execute different tasks defined in a single worker file. This example shows both CommonJS and ES Module syntax for initializing the pool. ```javascript 'use strict'; const Piscina = require('piscina'); const { resolve } = require('path'); const pool = new Piscina({ filename: resolve(__dirname, 'worker.js') }); (async () => { console.log(await Promise.all([ pool.run({ a: 2, b: 3 }, { name: 'add' }), pool.run({ a: 2, b: 3 }, { name: 'multiply' }) ])); })(); ``` ```javascript import { Piscina } from 'piscina'; const pool = new Piscina({ filename: new URL('./worker.mjs', import.meta.url).href }); console.log(await Promise.all([ pool.run({ a: 2, b: 3 }, { name: 'add' }), pool.run({ a: 2, b: 3 }, { name: 'multiply' }) ])); ``` -------------------------------- ### Configure Worker Environment and Runtime Options (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/worker-options.mdx Configure worker thread environments and runtime options using TypeScript. This example shows setting env, argv, and execArgv, along with workerData, for a TypeScript worker. ```typescript import { resolve } from 'path'; import Piscina from 'piscina'; import { filename } from './worker'; const piscina = new Piscina({ filename: resolve(__dirname, 'workerWrapper.js'), workerData: { fullpath: filename }, env: { A: '123' }, argv: ['a', 'b', 'c'], execArgv: ['--no-warnings'], }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```typescript import Piscina from 'piscina'; import { format } from 'util'; export default ({ a, b }: { a: number, b: number }): number => { console.log( ` process.argv: ${process.argv.slice(2)} process.execArgv: ${process.execArgv} process.env: ${format({ ...process.env })} workerData: ${Piscina.workerData}`); return a + b; }; ``` -------------------------------- ### Define Multiple Functions in a Worker File (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/multiple-workers-one-file.mdx Export a default handler function and additional named handlers for use with `pool.run({ name: '...' })`. This example uses CommonJS module syntax. ```javascript 'use strict'; function add ({ a, b }) { return a + b; } function multiply ({ a, b }) { return a * b; }; add.add = add; add.multiply = multiply; // The add function is the default handler, but // additional named handlers are exported. module.exports = add; ``` -------------------------------- ### Run ES Module Worker in TypeScript Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/es-module.mdx This example shows how to set up Piscina to use an ES module worker from a TypeScript main file. It utilizes Node.js path resolution and worker data passing. ```typescript import Piscina from "piscina"; import { resolve } from "path"; import { filename } from "./worker"; const piscina = new Piscina({ filename: resolve(__dirname, "./workerWrapper.js"), workerData: { fullpath: filename }, }); (async () => { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); })(); ``` -------------------------------- ### Configure Resource Limits in Main File (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/resource-limit.mdx Set resource limits for worker threads in the Piscina constructor. This configuration prevents workers from consuming excessive memory. The example limits the old generation to 16MB, young generation to 4MB, and code range to 16MB. ```javascript 'use strict'; const Piscina = require('piscina'); const { resolve } = require('path'); const { strictEqual } = require('assert'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js'), resourceLimits: { maxOldGenerationSizeMb: 16, maxYoungGenerationSizeMb: 4, codeRangeSizeMb: 16 } }); (async function () { try { await piscina.run(); } catch (err) { console.log('Worker terminated due to resource limits'); strictEqual(err.code, 'ERR_WORKER_OUT_OF_MEMORY'); } })(); ``` -------------------------------- ### Implement Transferable Interface Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/api-reference/interface.md Implement the `Transferable` interface to define custom transferable objects. Use `transferableSymbol` to specify objects for the transfer list and `valueSymbol` for a surrogate value. This example demonstrates transferring two `ArrayBuffer` objects. ```javascript const { move, transferableSymbol, valueSymbol } = require('piscina'); module.exports = () => { const obj = { a: { b: new Uint8Array(5); }, c: { new Uint8Array(10); }, get [transferableSymbol]() { // Transfer the two underlying ArrayBuffers return [this.a.b.buffer, this.c.buffer]; } get [valueSymbol]() { return { a: { b: this.a.b }, c: this.c }; } }; return move(obj); }; ``` -------------------------------- ### Build Native Addon Artifacts Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/n-api.mdx Execute this command to build the binary artifacts for the native addon, which will be placed in the 'prebuilds' folder. ```bash npm run prebuild ``` -------------------------------- ### Benchmark Server Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Run the autocannon benchmark against the local server. ```console $ autocannon localhost:3000 ``` -------------------------------- ### Main Script for Progress Tracking (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/progress.mdx The main script initializes Piscina, sets up progress bars for each task, and updates them based on messages from workers. It uses MessageChannel to facilitate communication. ```javascript 'use strict'; const Piscina = require('piscina'); const { resolve } = require('path'); const ProgressBar = require('progress'); // Initialize Piscina with the worker file const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js') }); // Function to create and run a task with progress tracking async function task(a, b) { // Create a progress bar for this task const bar = new ProgressBar(':bar [:current/:total]', { total: b }); // Set up a MessageChannel for communication with the worker const mc = new MessageChannel(); // Update the progress bar when a message is received from the worker mc.port2.onmessage = () => bar.tick(); // Prevent the port from keeping the event loop alive mc.port2.unref(); // Run the task in a worker, passing one port of the channel return await piscina.run({ a, b, port: mc.port1 }, { transferList: [mc.port1] }); } // Run multiple tasks concurrently Promise.all([ task(0, 50), task(0, 25), task(0, 90) ]).catch((err) => console.error(err)); ``` -------------------------------- ### Run Unpooled Synchronous Server Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Executes the unpooled synchronous sleep server and benchmarks it using autocannon. ```console $ node sync-sleep-unpooled ``` ```console $ autocannon localhost:3000 ``` -------------------------------- ### new Piscina([options]) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/api-reference/class.md Initializes a new Piscina worker pool instance with the provided configuration options. ```APIDOC ## Constructor: new Piscina([options]) ### Description Creates a new instance of the Piscina worker pool. The constructor accepts an optional configuration object to tune worker behavior, resource limits, and task scheduling. ### Parameters - **resourceLimits** (object) - Optional - Configuration for worker thread heap and stack sizes. - **env** (object) - Optional - Initial environment variables for worker threads. - **argv** (any[]) - Optional - Arguments appended to process.argv in the worker. - **execArgv** (string[]) - Optional - Node.js CLI options passed to the worker. - **workerData** (any) - Optional - Data made available as require('piscina').workerData. - **taskQueue** (TaskQueue) - Optional - Custom implementation for task queuing. - **niceIncrement** (number) - Optional - Value to decrease thread priority. - **trackUnmanagedFds** (boolean) - Optional - Whether to track and auto-close file descriptors. Defaults to true. - **closeTimeout** (number) - Optional - Time in ms to wait for tasks to complete on close. Defaults to 30000. - **recordTiming** (boolean) - Optional - Whether to record run and wait time. Defaults to true. - **workerHistogram** (boolean) - Optional - Whether to record statistics for individual workers. Defaults to false. - **loadBalancer** (PiscinaLoadBalancer) - Optional - Custom load balancing implementation. ``` -------------------------------- ### Run Multiple Workers with Piscina Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/multiple-workers.mdx Pass the worker filename to the `run` method to execute tasks on different workers from a single pool. This example runs an addition and a multiplication task concurrently. ```javascript "use strict"; const Piscina = require("piscina"); const { resolve } = require("path"); const pool = new Piscina(); (async () => { console.log( await Promise.all([ pool.run({ a: 2, b: 3 }, { filename: resolve(__dirname, "add_worker") }), pool.run( { a: 2, b: 3 }, { filename: resolve(__dirname, "multiply_worker") } ), ]) ); })(); ``` -------------------------------- ### Main Script for Stream Processing (index.mjs) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/stream.mdx Sets up a pipeline to read a file, process its contents in a worker thread, and output the result. Requires a worker script and stream utility classes. ```javascript import Piscina from 'piscina'; import { MessagePortDuplex } from './stream.mjs'; import { createReadStream } from 'fs'; import { pipeline } from 'stream'; const pool = new Piscina({ filename: new URL('./worker.mjs', import.meta.url).href }); const { port1, port2 } = new MessageChannel(); pool.run(port2, { transferList: [port2] }); const duplex = new MessagePortDuplex(port1); pipeline( createReadStream(new URL('./index.mjs', import.meta.url).pathname), duplex, process.stdout, (err) => { if (err) throw err; }); ``` -------------------------------- ### Unpooled Asynchronous Scrypt and RandomFill Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/scrypt.mdx Demonstrates the unpooled asynchronous usage of scrypt and randomFill. This approach avoids blocking the event loop but may incur slightly higher overhead. It measures the performance of generating keys over multiple iterations. ```javascript 'use strict'; const crypto = require('crypto'); const { promisify } = require('util'); const randomFill = promisify(crypto.randomFill); const scrypt = promisify(crypto.scrypt); const { performance, PerformanceObserver } = require('perf_hooks'); const salt = Buffer.allocUnsafe(16); const obs = new PerformanceObserver((entries) => { console.log(entries.getEntries()[0].duration); }); obs.observe({ entryTypes: ['measure'] }); async function * generateInput () { let max = parseInt(process.argv[2] || 10); const data = Buffer.allocUnsafe(10); while (max-- > 0) { yield randomFill(data); } } (async function () { performance.mark('start'); const keylen = 64; for await (const input of generateInput()) { (await scrypt(input, await randomFill(salt), keylen)).toString('hex'); } performance.mark('end'); performance.measure('start to end', 'start', 'end'); })(); ``` ```typescript 'use strict'; import crypto from 'crypto'; import { promisify } from 'util'; const randomFill = promisify(crypto.randomFill); const scrypt:any = promisify(crypto.scrypt); const { performance, PerformanceObserver } = require('perf_hooks'); const salt = Buffer.allocUnsafe(16); const obs = new PerformanceObserver((entries: { getEntries: () => { duration: any; }[]; }) => { console.log(entries.getEntries()[0].duration); }); obs.observe({ entryTypes: ['measure'] }); async function* generateInput() { let max = parseInt(process.argv[2] || '10', 10); const data = Buffer.allocUnsafe(10); while (max-- > 0) { yield randomFill(data); } } (async function () { performance.mark('start'); const keylen = 64; for await (const input of generateInput()) { (await scrypt(input, await randomFill(salt), keylen)).toString('hex'); } performance.mark('end'); performance.measure('start to end', 'start', 'end'); })(); ``` -------------------------------- ### Worker script for Task Queue Example (Typescript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/task-queue.mdx TypeScript version of the worker script. It simulates asynchronous work using `setTimeout` and logs the priority of the processed task, returning the priority value. ```typescript import { promisify } from 'util'; const sleep = promisify(setTimeout); export default async ({ priority }: { priority: number }): Promise => { await sleep(100); process._rawDebug(`${priority}`); return priority; }; export const filename = __filename; ``` -------------------------------- ### Pooled React SSR with Fastify (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/react-ssr.mdx Sets up a Fastify server with `fastify-piscina` to run React SSR tasks in worker threads. Configure the worker file, thread count, and use `fastify.runTask()` to execute rendering. ```javascript 'use strict'; const fastify = require('fastify')(); const { resolve } = require('path'); fastify.register(require('fastify-piscina'), { filename: resolve(__dirname, 'worker.js'), execArgv: [], minThreads: 6, maxThreads: 6 }); // Declare a route fastify.get('/', async () => fastify.runTask({ name: 'James' })); // Run the server! const start = async () => { try { await fastify.listen({ port: 3000 }); } catch (err) { process.exit(1); } }; start(); process.on('SIGINT', () => { const waitTime = fastify.piscina.waitTime; console.log('\nMax Queue Wait Time:', waitTime.max); console.log('Mean Queue Wait Time:', waitTime.mean); process.exit(0); }); ``` -------------------------------- ### close([options]) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/api-reference/method.md Stops all worker threads gracefully, waiting for started tasks to complete. Optionally, it can force abort pending tasks. Returns a Promise that resolves when all tasks are completed and threads have stopped. ```APIDOC ## Method: `close([options])` * `options`: * `force`: A `boolean` value that indicates whether to abort all tasks that are enqueued but not started yet. The default is `false`. It stops all Workers gracefully. This returns a `Promise` that is fulfilled once all tasks that were started have completed and all threads have stopped. This method is similar to `destroy()`, but with the difference that `close()` will wait for the worker tasks to finish, while `destroy()` will abort them immediately. ``` -------------------------------- ### Run Pooled Synchronous Server Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/server.mdx Executes the pooled synchronous sleep server and benchmarks it using autocannon. ```console $ node sync-sleep-pooled ``` ```console $ autocannon localhost:3000 ``` -------------------------------- ### TypeScript Worker File Example Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/typescript.mdx Defines a TypeScript worker function that adds two numbers. This file would typically be compiled to JavaScript before being used by Piscina, or used with native Node.js TypeScript support. ```typescript import { resolve } from 'path'; export const filename = resolve(__filename); interface Inputs { a: number; b: number; } export function addNumbers({ a, b }: Inputs): number { return a + b; } ``` -------------------------------- ### Main Script for Web Streams Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/webstreams.mdx This script sets up a Piscina instance, creates a readable stream emitting numbers and a writable stream logging chunks, then runs a task in the worker pool. Streams are transferred to the worker using `transferList`. ```javascript import Piscina from 'piscina'; import { ReadableStream, WritableStream } from 'node:stream/web'; const pool = new Piscina({ filename: new URL('./worker.mjs', import.meta.url).href }); const readable = new ReadableStream({ start () { this.chunks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; }, pull (controller) { const chunk = this.chunks.shift(); controller.enqueue(chunk); if (this.chunks.length === 0) { controller.close(); } } }); const writable = new WritableStream({ write (chunk) { console.log(chunk); } }); (async function () { await pool.run({ readable, writable }, { transferList: [readable, writable] }); })(); ``` -------------------------------- ### Build Static Website Content Source: https://github.com/piscinajs/piscina/blob/current/docs/README.md Generates the static files for the website, typically placed in the 'build' directory. These files can then be deployed to any static hosting service. ```bash $ npm run build ``` -------------------------------- ### Cancel Task with AbortController (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx Implement task cancellation in TypeScript using `AbortController`. The worker setup includes the worker file and necessary worker data. The cancellation is handled within a try-catch block. ```typescript import Piscina from "piscina"; import { resolve } from "path"; import { filename } from "./worker"; // Set up Piscina with the worker and workerWrapper file const piscina = new Piscina({ filename: resolve(__dirname, "./workerWrapper.js"), workerData: { fullpath: filename }, }); // Run a task and cancel it using AbortController (async () => { const abortController = new AbortController(); const { signal } = abortController; const task = piscina.run({ a: 4, b: 6 }, { signal }); abortController.abort(); // Cancel the task try { await task; } catch (err) { console.log("The task was canceled"); // Handle the cancellation } })(); ``` -------------------------------- ### Web Streams Pipeline with Piscina (MJS) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/webstreams-transform.mdx Main script to set up a Web Streams pipeline. It creates a readable stream, a transform stream using a Piscina worker, and a writable stream to log output. ```javascript import Piscina from 'piscina'; import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web'; const pool = new Piscina({ filename: new URL('./worker.mjs', import.meta.url).href }); const readable = new ReadableStream({ start () { this.chunks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; }, pull (controller) { const chunk = this.chunks.shift(); controller.enqueue(chunk); if (this.chunks.length === 0) { controller.close(); } } }); const writable = new WritableStream({ write (chunk) { console.log(chunk); } }); const transform = new TransformStream({ async transform (chunk, controller) { controller.enqueue(await pool.run(chunk)); } }); readable.pipeThrough(transform).pipeTo(writable); ``` -------------------------------- ### Method: run(task[, options]) Source: https://github.com/piscinajs/piscina/blob/current/README.md Executes a task in the worker pool. ```APIDOC ## run(task[, options]) ### Description Submits a task to the worker pool for execution. ### Parameters - **task** (any) - Required - The task data to be processed by the worker. - **options** (Object) - Optional - Execution options for the specific task. ``` -------------------------------- ### Main Script for Progress Tracking (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/progress.mdx The TypeScript version of the main script configures Piscina and uses MessageChannel for progress updates. It requires a worker wrapper for initialization. ```typescript import Piscina from "piscina"; import { resolve } from "path"; import { filename } from "./worker"; import ProgressBar from 'progress'; const piscina = new Piscina({ filename: resolve(__dirname, "./workerWrapper.js"), workerData: { fullpath: filename }, }); async function task(a: number, b: number): Promise { // Create a progress bar for this task const bar = new ProgressBar(':bar [:current/:total]', { total: b }); // Set up a MessageChannel for communication with the worker const mc = new MessageChannel(); // Update the progress bar when a message is received from the worker mc.port2.onmessage = () => bar.tick(); // Prevent the port from keeping the event loop alive mc.port2.unref(); // Run the task in a worker, passing one port of the channel await piscina.run({ a, b, port: mc.port1 }, { transferList: [mc.port1], name: 'progressTask' }); } // Run multiple tasks concurrently Promise.all([ task(0, 50), task(0, 25), task(0, 90) ]).catch((err) => console.error(err)); ``` -------------------------------- ### Running Multiple Tasks Concurrently (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/getting-started/basic-usage.mdx Initialize Piscina with a worker file and then run multiple tasks concurrently using `Promise.all`, specifying the handler function name. ```javascript "use strict"; const Piscina = require("piscina"); const { resolve } = require("path"); // Initialize Piscina with the worker file const piscina = new Piscina({ filename: resolve(__dirname, "worker.js"), }); // Run multiple tasks concurrently (async () => { const [sum, product] = await Promise.all([ piscina.run({ a: 4, b: 6 }, { name: "add" }), piscina.run({ a: 4, b: 6 }, { name: "multiply" }), ]); })(); ``` -------------------------------- ### Unpooled Synchronous Scrypt (JavaScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/scrypt.mdx Demonstrates a synchronous scrypt implementation using Node.js crypto module. It generates random inputs and hashes them using scryptSync, measuring performance. Ensure Node.js crypto is available. ```javascript 'use strict'; const crypto = require('crypto'); const { promisify } = require('util'); const { scryptSync, randomFillSync } = crypto; const randomFill = promisify(crypto.randomFill); const { performance, PerformanceObserver } = require('perf_hooks'); const salt = Buffer.allocUnsafe(16); const obs = new PerformanceObserver((entries) => { console.log(entries.getEntries()[0].duration); }); obs.observe({ entryTypes: ['measure'] }); async function * generateInput () { let max = parseInt(process.argv[2] || 10); const data = Buffer.allocUnsafe(10); while (max-- > 0) { yield randomFill(data); } } (async function () { performance.mark('start'); const keylen = 64; for await (const input of generateInput()) { // Everything in here is intentionally sync scryptSync(input, randomFillSync(salt), keylen).toString('hex'); } performance.mark('end'); performance.measure('start to end', 'start', 'end'); })(); ``` -------------------------------- ### Unpooled Synchronous Scrypt (TypeScript) Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/scrypt.mdx Provides a TypeScript function for synchronous scrypt hashing. It accepts input, key length, and optional scrypt parameters (N, r, p, maxmem). Requires Node.js crypto and TypeScript setup. ```typescript 'use strict'; import { scryptSync, randomFillSync } from 'crypto'; const salt = Buffer.allocUnsafe(16); export default function ({ input, keylen, N = 16384, r = 8, p = 1, maxmem = 32 * 1024 * 1024 }: { input: Buffer; keylen: number; N?: number; r?: number; p?: number; maxmem?: number; }): string { return scryptSync(input, randomFillSync(salt), keylen, { N, r, p, maxmem }).toString('hex'); } ``` -------------------------------- ### Async Worker with JavaScript Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/simple_async.mdx Sets up a Piscina worker to perform an asynchronous addition. The worker simulates a delay before returning the result. Requires 'piscina' and 'path' modules. ```javascript 'use strict'; const Piscina = require('../..'); const { resolve } = require('path'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js') }); (async function () { const result = await piscina.run({ a: 4, b: 6 }); console.log(result); // Prints 10 })(); ``` ```javascript 'use strict'; const { promisify } = require('util'); const sleep = promisify(setTimeout); module.exports = async ({ a, b }) => { // Fake some async activity await sleep(100); return a + b; }; ``` -------------------------------- ### Run Named Tasks in Javascript Source: https://github.com/piscinajs/piscina/blob/current/docs/docs/examples/named.mdx This script initializes Piscina and uses a dispatcher pattern to run 'add' and 'sub' tasks concurrently. Ensure the worker file and helper functions are correctly set up. ```javascript 'use strict'; const Piscina = require('piscina'); const { resolve } = require('path'); const { makeTask } = require('./helper'); const piscina = new Piscina({ filename: resolve(__dirname, 'worker.js') }); (async function () { const result = await Promise.all([ piscina.run(makeTask('add', 4, 6)), piscina.run(makeTask('sub', 4, 6)) ]); console.log(result); })(); ```