ForgeTotal.js 5
es

Total.js 5

Comparte unos pocos hilos de trabajo con NEWTHREADPOOL()

Total.js 5 · total5@0.0.19 workerthreadpoolperformance Ejecutada con Total.js 5

NEWTHREAD() arranca un worker. Cuando muchas peticiones necesitan el mismo trabajo pesado, un worker por petición son demasiados y un único worker hace que se esperen unas a otras sin ningún orden. NEWTHREADPOOL(name, count, [isfork]) arranca count workers de workers/name.js (un hilo; con isfork en true, un proceso hijo, como NEWFORK()) y los reparte de uno en uno.

  • pool.exec(function(worker, release) {}) espera hasta que hay un worker libre y llama a tu función con él. Envíale el trabajo con worker.postMessage(value), lee la respuesta con worker.once('message', fn) y llama a release() cuando termines: el worker vuelve al pool y lo toma el siguiente trabajo que espera.
  • Sin función, pool.exec() devuelve una promesa que se resuelve con worker (y el worker tiene worker.release()), de modo que funciona con await.
  • Los trabajos se atienden en el orden en que lo pidieron. El pool no encola los mensajes de un worker: un trabajo a la vez lo tiene.
  • El pool también se guarda en F.workers[name]. pool.workers es la lista de los workers.

El archivo del worker es el mismo que para NEWTHREAD(): NEWTHREAD() dentro de él devuelve el manejador con worker.message y worker.postMessage(). Aquí cada worker suma los números e indica qué hilo lo hizo.

workers/total.js
require('total5');

const worker = NEWTHREAD();

worker.message = function(message) {
	let total = 0;
	for (let i = 1; i <= message.to; i++)
		total += i;
	worker.postMessage({ to: message.to, total: total, thread: require('worker_threads').threadId });
};
controllers/total.js
exports.install = function() {
	ROUTE('GET /total/{to}/', total);
	ROUTE('GET /await/{to}/', total_await);
	ROUTE('GET /workers/', workers);
};

const pool = NEWTHREADPOOL('total', 2);

function total($) {
	pool.exec(function(worker, release) {
		worker.once('message', function(response) {
			release();
			$.json(response);
		});
		worker.postMessage({ to: +$.params.to });
	});
}

async function total_await($) {
	const worker = await pool.exec();
	worker.once('message', function(response) {
		worker.release();
		$.json(response);
	});
	worker.postMessage({ to: +$.params.to });
}

function workers($) {
	$.json({ workers: pool.workers.length, registered: F.workers.total === pool });
}