From 7d75971d2f7225526a704e30cec2bb26154b6612 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Tue, 4 Mar 2025 12:46:21 -0800 Subject: [PATCH] Scrap worker idea for now. --- src/classes/cpu.ts | 42 +++------ src/classes/pow-pool.ts | 142 ------------------------------- src/classes/pow-worker-export.ts | 7 -- src/classes/pow-worker.ts | 39 --------- 4 files changed, 14 insertions(+), 216 deletions(-) delete mode 100644 src/classes/pow-pool.ts delete mode 100644 src/classes/pow-worker-export.ts delete mode 100644 src/classes/pow-worker.ts diff --git a/src/classes/cpu.ts b/src/classes/cpu.ts index d6e9336..48ee456 100644 --- a/src/classes/cpu.ts +++ b/src/classes/cpu.ts @@ -172,34 +172,20 @@ export class NanoPowCpu { : options.effort this.#debug = !!(options?.debug) - - return new Promise(async (resolve, reject): Promise => { - if (NanoPow == null) throw new Error('NanoPow not available') - for (const d of data) { - try { - d.work = await NanoPow.search(d.hash, d.threshold) - } catch (err) { - reject(err) - } - } - resolve(data) - - - let attempts = 0n - let result = 0n - let nonce = 0n - let start = performance.now() - do { - attempts++ - const random0 = Math.floor(Math.random() * 0xffffffff) - const random1 = Math.floor(Math.random() * 0xffffffff) - nonce = (BigInt(random0) << 32n) | BigInt(random1) - result = this.#hash(nonce, hash) - } while (result < threshold) - console.log(performance.now() - start) - this.#busy = false - resolve(result.toString(16).padStart(16, '0')) - }) + let attempts = 0n + let result = 0n + let nonce = 0n + let start = performance.now() + do { + attempts++ + const random0 = Math.floor(Math.random() * 0xffffffff) + const random1 = Math.floor(Math.random() * 0xffffffff) + nonce = (BigInt(random0) << 32n) | BigInt(random1) + result = this.#hash(nonce, hash) + } while (result < threshold) + console.log(performance.now() - start) + this.#busy = false + return result.toString(16).padStart(16, '0') } /** diff --git a/src/classes/pow-pool.ts b/src/classes/pow-pool.ts deleted file mode 100644 index 2df8b34..0000000 --- a/src/classes/pow-pool.ts +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later - -type Job = { - id: number - reject: (value: any) => void - resolve: (value: any) => void - data: any - results: any[] -} - -type Thread = { - worker: Worker - job: Job | null -} - -/** -* Processes an array of tasks using Web Workers. -*/ -export class Pool { - static #cores: number = Math.max(1, navigator.hardwareConcurrency - 1) - #queue: Job[] = [] - #threads: Thread[] = [] - #url: string - - get threadsBusy (): number { - let n = 0 - for (const thread of this.#threads) { - n += +(thread.job != null) - } - return n - } - get threadsIdle (): number { - let n = 0 - for (const thread of this.#threads) { - n += +(thread.job == null) - } - return n - } - - async assign (data: any): Promise { - if (!(data instanceof ArrayBuffer || Array.isArray(data))) data = [data] - return new Promise((resolve, reject) => { - const job: Job = { - id: performance.now(), - results: [], - data, - resolve, - reject - } - if (this.#queue.length > 0) { - this.#queue.push(job) - } else { - for (const thread of this.#threads) this.#assign(thread, job) - } - }) - } - - /** - * - * @param {string} worker - Stringified worker class - * @param {number} [count=1] - Integer between 1 and CPU thread count shared among all Pools - */ - constructor (worker: string, count: number = 1) { - count = Math.min(Pool.#cores, Math.max(1, Math.floor(Math.abs(count)))) - this.#url = URL.createObjectURL(new Blob([worker], { type: 'text/javascript' })) - for (let i = 0; i < count; i++) { - const thread = { - worker: new Worker(this.#url, { type: 'module' }), - job: null - } - thread.worker.addEventListener('message', message => { - let result = JSON.parse(new TextDecoder().decode(message.data) || "[]") - if (!Array.isArray(result)) result = [result] - this.#report(thread, result) - }) - this.#threads.push(thread) - Pool.#cores = Math.max(1, Pool.#cores - this.#threads.length) - } - } - - #assign (thread: Thread, job: Job): void { - if (job.data instanceof ArrayBuffer) { - if (job.data.byteLength > 0) { - thread.job = job - thread.worker.postMessage({ buffer: job.data }, [job.data]) - } - } else { - const chunk: number = 1 + (job.data.length / this.threadsIdle) - const next = job.data.slice(0, chunk) - job.data = job.data.slice(chunk) - if (job.data.length === 0) this.#queue.shift() - if (next?.length > 0) { - const buffer = new TextEncoder().encode(JSON.stringify(next)).buffer - thread.job = job - thread.worker.postMessage({ buffer }, [buffer]) - } - } - } - - #isJobDone (jobId: number): boolean { - for (const thread of this.#threads) { - if (thread.job?.id === jobId) return false - } - return true - } - - #report (thread: Thread, results: any[]): void { - if (thread.job == null) { - throw new Error('Thread returned results but had nowhere to report it.') - } - const job = thread.job - if (this.#queue.length > 0) { - this.#assign(thread, this.#queue[0]) - } else { - thread.job = null - } - if (results.length > 0) { - job.results.push(...results) - } - if (this.#isJobDone(job.id)) { - job.resolve(job.results) - } - } -} - -/** -* Provides basic worker event messaging to extending classes. -* -* In order to be properly bundled in a format that can be used to create an -* inline Web Worker, the extending classes must export WorkerInterface and -* themselves as a string: -*``` -* export default ` -* const WorkerInterface = ${WorkerInterface} -* const Pow = ${Pow} -* ` -* ``` -* They must also initialize the event listener by calling their inherited -* `listen()` function. Finally, they must override the implementation of the -* `work()` function. See the documentation of those functions for details. -*/ diff --git a/src/classes/pow-worker-export.ts b/src/classes/pow-worker-export.ts deleted file mode 100644 index 9616073..0000000 --- a/src/classes/pow-worker-export.ts +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later -import { default as NanoPowWorker } from '#~/workers/nano-pow.js' - -export { - NanoPowWorker -} diff --git a/src/classes/pow-worker.ts b/src/classes/pow-worker.ts deleted file mode 100644 index cbba79d..0000000 --- a/src/classes/pow-worker.ts +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Chris Duncan -// SPDX-License-Identifier: GPL-3.0-or-later -import { WorkerInterface } from '#~/pool.js' -import { NanoPow } from 'nano-pow' - -/** -* Nano proof-of-work using WebGPU and Web Workers. -*/ -export class NanoPowWorker extends WorkerInterface { - static { - NanoPowWorker.listen() - } - - /** - * Calculates proof-of-work as described by the Nano cryptocurrency protocol. - * - * @param {any[]} data - Array of hashes and minimum thresholds - * @returns Promise for proof-of-work attached to original array objects - */ - static async work (data: any[]): Promise { - return new Promise(async (resolve, reject): Promise => { - if (NanoPow == null) throw new Error('NanoPow not available') - for (const d of data) { - try { - d.work = await NanoPow.search(d.hash, d.threshold) - } catch (err) { - reject(err) - } - } - resolve(data) - }) - } -} - -export default ` - const NanoPow = ${NanoPow} - const WorkerInterface = ${WorkerInterface} - const NanoPowWorker = ${NanoPowWorker} -` -- 2.34.1