Files
salvium-rs/test/legacy-js/test-process-parallel.js
Matt Hess 733ecd2681 Migrate all JS tests to Rust: 9-crate workspace, 703 tests, 0 JS remaining
Add root Cargo workspace with 9 crates: salvium-crypto (extended),
  salvium-types, salvium-consensus, salvium-wallet, salvium-tx,
  salvium-rpc, salvium-miner (extended), salvium-cli, salvium-multisig.

  New modules: chain_state, block_weight, alt_chain, validation,
  offline signing, stake lifecycle, wallet sync/query/encryption/utxo,
  randomx utilities, and full multisig crate with CARROT support.

  Delete 188 JS test/helper/debug files; archive integration test
  scripts to test/legacy-js/ for live testnet use. Testnet integration
  tests (transfer, stake, burn, convert, sweep) remain as #[ignore]-
  gated Rust tests runnable with --ignored against a live daemon.
2026-02-17 23:09:35 +00:00

103 lines
2.9 KiB
JavaScript

/**
* Test Child Process Parallelism
*
* Uses child_process.fork() instead of worker_threads to get
* true process isolation and parallel WASM execution.
*/
import { fork } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const workerScript = join(__dirname, 'process-worker.js');
async function testProcesses(numProcesses, hashesPerProcess) {
console.log(`\n--- ${numProcesses} process(es), ${hashesPerProcess} hashes each ---`);
const processes = [];
const results = [];
const initStart = Date.now();
// Create processes
for (let i = 0; i < numProcesses; i++) {
const child = fork(workerScript, [String(i), String(hashesPerProcess)], {
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
});
const resultPromise = new Promise((resolve) => {
child.on('message', (msg) => {
if (msg.type === 'ready') {
console.log(` Process ${i} ready`);
} else if (msg.type === 'done') {
resolve(msg);
}
});
});
processes.push({ child, resultPromise });
}
// Wait for all to be ready
await Promise.all(processes.map(p => new Promise(r => {
p.child.once('message', (msg) => {
if (msg.type === 'ready') r();
});
})));
const initTime = Date.now() - initStart;
console.log(`Init time: ${initTime}ms`);
// Start all processes
console.log('Starting hashing...');
const hashStart = Date.now();
for (const { child } of processes) {
child.send({ type: 'start' });
}
// Wait for results
const allResults = await Promise.all(processes.map(p => p.resultPromise));
const totalTime = Date.now() - hashStart;
let totalHashes = 0;
for (const { workerId, hashCount, elapsed } of allResults) {
console.log(` Process ${workerId}: ${hashCount} hashes in ${elapsed}ms`);
totalHashes += hashCount;
}
const hps = totalHashes / (totalTime / 1000);
console.log(`Total: ${totalHashes} hashes in ${totalTime}ms (${hps.toFixed(2)} H/s)`);
// Kill processes
for (const { child } of processes) {
child.kill();
}
return hps;
}
async function main() {
console.log('Child Process Hash Test');
console.log('=======================');
console.log('(Using fork() for true process isolation)');
const hashesPerProcess = 10;
const hps1 = await testProcesses(1, hashesPerProcess);
const hps2 = await testProcesses(2, hashesPerProcess);
const hps4 = await testProcesses(4, hashesPerProcess);
console.log('\n=== Summary ===');
console.log(`1 process: ${hps1.toFixed(2)} H/s`);
console.log(`2 processes: ${hps2.toFixed(2)} H/s (${(hps2/hps1).toFixed(2)}x)`);
console.log(`4 processes: ${hps4.toFixed(2)} H/s (${(hps4/hps1).toFixed(2)}x)`);
if (hps4 >= hps1 * 3) {
console.log('\n✓ Child processes scale well!');
} else {
console.log('\n✗ Scaling is limited (possibly memory bandwidth)');
}
}
main().catch(console.error);