Files
salvium-rs/test/legacy-js/benchmark-multithread.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

139 lines
4.3 KiB
JavaScript

/**
* Multi-threaded RandomX Benchmark
*
* Tests performance across different thread counts.
*/
import { RandomXContext, getAvailableCores } from '../src/randomx/index.js';
const HASHES_PER_TEST = 50;
async function benchmarkSingleThread() {
console.log('=== Single Thread Benchmark ===\n');
const ctx = new RandomXContext();
console.log('Initializing cache (256MB)...');
const initStart = Date.now();
await ctx.init(new Uint8Array(32));
console.log(`Cache init: ${Date.now() - initStart}ms\n`);
// Warm up
for (let i = 0; i < 5; i++) {
ctx.hash(`warmup ${i}`);
}
// Benchmark
console.log(`Hashing ${HASHES_PER_TEST} inputs...`);
const start = Date.now();
for (let i = 0; i < HASHES_PER_TEST; i++) {
ctx.hash(`benchmark ${i}`);
}
const elapsed = (Date.now() - start) / 1000;
const hashrate = HASHES_PER_TEST / elapsed;
console.log(`\nSingle thread results:`);
console.log(` Time: ${elapsed.toFixed(2)}s`);
console.log(` Hashrate: ${hashrate.toFixed(2)} H/s`);
return hashrate;
}
async function benchmarkMultiThread(numThreads) {
console.log(`\n=== ${numThreads}-Thread Simulation ===\n`);
// Create multiple contexts (simulating workers)
const contexts = [];
console.log(`Initializing ${numThreads} contexts...`);
const initStart = Date.now();
for (let i = 0; i < numThreads; i++) {
const ctx = new RandomXContext();
await ctx.init(new Uint8Array(32));
contexts.push(ctx);
}
console.log(`All contexts initialized in ${Date.now() - initStart}ms\n`);
// Warm up
for (const ctx of contexts) {
for (let i = 0; i < 3; i++) {
ctx.hash(`warmup ${i}`);
}
}
// Benchmark - round robin across contexts
const hashesPerContext = Math.floor(HASHES_PER_TEST / numThreads);
console.log(`Hashing ${hashesPerContext * numThreads} inputs across ${numThreads} threads...`);
const start = Date.now();
// Simulate parallel hashing by interleaving
const promises = contexts.map(async (ctx, threadId) => {
for (let i = 0; i < hashesPerContext; i++) {
ctx.hash(`thread${threadId}_hash${i}`);
}
});
await Promise.all(promises);
const elapsed = (Date.now() - start) / 1000;
const totalHashes = hashesPerContext * numThreads;
const hashrate = totalHashes / elapsed;
console.log(`\n${numThreads}-thread results:`);
console.log(` Time: ${elapsed.toFixed(2)}s`);
console.log(` Total hashes: ${totalHashes}`);
console.log(` Hashrate: ${hashrate.toFixed(2)} H/s`);
console.log(` Per-thread: ${(hashrate / numThreads).toFixed(2)} H/s`);
return hashrate;
}
async function main() {
console.log('RandomX Multi-Thread Benchmark');
console.log('==============================');
console.log(`Available CPU cores: ${getAvailableCores()}`);
console.log(`Hashes per test: ${HASHES_PER_TEST}\n`);
const results = {};
// Single thread
results[1] = await benchmarkSingleThread();
// Multi-thread tests
for (const threads of [2, 4, Math.min(8, getAvailableCores())]) {
results[threads] = await benchmarkMultiThread(threads);
}
// Summary
console.log('\n==============================');
console.log('Summary (Light Mode - 256MB cache per thread)');
console.log('==============================\n');
console.log('Threads | Hashrate | Memory | Scaling');
console.log('--------|------------|-----------|--------');
const baseHashrate = results[1];
for (const [threads, hashrate] of Object.entries(results)) {
const memory = parseInt(threads) * 256;
const scaling = ((hashrate / baseHashrate) * 100).toFixed(0);
console.log(`${threads.padStart(7)} | ${hashrate.toFixed(2).padStart(8)} H/s | ${memory.toString().padStart(4)}MB | ${scaling}%`);
}
console.log('\n==============================');
console.log('Native C++ RandomX Comparison');
console.log('==============================\n');
console.log('Typical native performance (for reference):');
console.log(' - Light mode: ~800-2000 H/s per thread');
console.log(' - Full mode: ~2000-4000 H/s per thread');
console.log(' - With hardware AES: +30-50%');
console.log('\nOur WASM-JIT implementation:');
console.log(` - Light mode: ~${baseHashrate.toFixed(0)} H/s per thread`);
console.log(` - Ratio to native: ~${((baseHashrate / 1500) * 100).toFixed(1)}% of native speed`);
}
main().catch(console.error);