summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/source/nollamas/index.js118
-rw-r--r--web/source/nollamasworker/index.js20
2 files changed, 87 insertions, 51 deletions
diff --git a/web/source/nollamas/index.js b/web/source/nollamas/index.js
index e8ae0a75c..b04a97c23 100644
--- a/web/source/nollamas/index.js
+++ b/web/source/nollamas/index.js
@@ -45,51 +45,85 @@ document.addEventListener("DOMContentLoaded", function() {
// data attributes on the nollamas section.
const seed = nollamas.dataset.nollamasSeed;
const challenge = nollamas.dataset.nollamasChallenge;
+ const threads = navigator.hardwareConcurrency;
+ if (typeof(threads) != "number" || threads < 1) { threads = 1; }
console.log("seed:", seed); // eslint-disable-line no-console
console.log("challenge:", challenge); // eslint-disable-line no-console
+ console.log("threads:", threads); // eslint-disable-line no-console
- // Prepare the worker with task function.
- const worker = new Worker("/assets/dist/nollamasworker.js");
+ // Create an array to track
+ // all workers such that we
+ // can terminate them all.
+ const workers = [];
+ const terminateAll = () => { workers.forEach((worker) => worker.terminate() ); };
+
+ // Get time before task completion.
const startTime = performance.now();
- worker.postMessage({
- challenge: challenge,
- seed: seed,
- });
-
- // Set the main worker function.
- worker.onmessage = function (e) {
- if (e.data.done) {
- const endTime = performance.now();
- const duration = endTime - startTime;
-
- // Remove spinner and replace it with a tick
- // and info about how long it took to solve.
- nollamas.removeChild(spinner);
- const solutionWrapper = document.createElement("div");
- solutionWrapper.className = "nollamas-status";
-
- const tick = document.createElement("i");
- tick.className = "fa fa-check fa-2x fa-fw";
- tick.setAttribute("title","Solved!");
- tick.setAttribute("aria-label", "Solved!");
- solutionWrapper.appendChild(tick);
-
- const took = document.createElement("span");
- const solvedText = `Solved after ${e.data.nonce} iterations, in ${duration.toString()}ms!`;
- took.appendChild(document.createTextNode(solvedText));
- solutionWrapper.appendChild(took);
-
- nollamas.appendChild(solutionWrapper);
-
- // Wait for 500ms before redirecting, to give
- // visitors a shot at reading the message, but
- // not so long that they have to wait unduly.
- setTimeout(() => {
- let url = new URL(window.location.href);
- url.searchParams.set("nollamas_solution", e.data.nonce);
- window.location.replace(url.toString());
- }, 500);
- }
- };
+
+ // Prepare and start each worker,
+ // adding them to the workers array.
+ for (let i = 0; i < threads; i++) {
+ const worker = new Worker("/assets/dist/nollamasworker.js");
+ workers.push(worker);
+
+ // On any error terminate.
+ worker.onerror = (ev) => {
+ console.error("worker error:", ev); // eslint-disable-line no-console
+ terminateAll();
+ };
+
+ // Post worker message, where each
+ // worker will compute nonces in range:
+ // $threadNumber + $totalThreads * n
+ worker.postMessage({
+ challenge: challenge,
+ threads: threads,
+ thread: i,
+ seed: seed,
+ });
+
+ // Set main on-success function.
+ worker.onmessage = function (e) {
+ if (e.data.done) {
+ // Stop workers.
+ terminateAll();
+
+ // Log which thread found the solution.
+ console.log("solution from:", e.data.thread); // eslint-disable-line no-console
+
+ // Get total computation duration.
+ const endTime = performance.now();
+ const duration = endTime - startTime;
+
+ // Remove spinner and replace it with a tick
+ // and info about how long it took to solve.
+ nollamas.removeChild(spinner);
+ const solutionWrapper = document.createElement("div");
+ solutionWrapper.className = "nollamas-status";
+
+ const tick = document.createElement("i");
+ tick.className = "fa fa-check fa-2x fa-fw";
+ tick.setAttribute("title","Solved!");
+ tick.setAttribute("aria-label", "Solved!");
+ solutionWrapper.appendChild(tick);
+
+ const took = document.createElement("span");
+ const solvedText = `Solved after ${e.data.nonce} iterations by worker ${e.data.thread} of ${threads}, in ${duration.toString()}ms!`;
+ took.appendChild(document.createTextNode(solvedText));
+ solutionWrapper.appendChild(took);
+
+ nollamas.appendChild(solutionWrapper);
+
+ // Wait for 500ms before redirecting, to give
+ // visitors a shot at reading the message, but
+ // not so long that they have to wait unduly.
+ setTimeout(() => {
+ let url = new URL(window.location.href);
+ url.searchParams.set("nollamas_solution", e.data.nonce);
+ window.location.replace(url.toString());
+ }, 500);
+ }
+ };
+ }
});
diff --git a/web/source/nollamasworker/index.js b/web/source/nollamasworker/index.js
index 3c9b043c2..0a7711ce1 100644
--- a/web/source/nollamasworker/index.js
+++ b/web/source/nollamasworker/index.js
@@ -19,10 +19,10 @@
import sha256 from "./sha256";
-let compute = async function(seedStr, challengeStr) {
+let compute = async function(seedStr, challengeStr, start, iter) {
const textEncoder = new TextEncoder();
- let nonce = 0;
+ let nonce = start;
while (true) { // eslint-disable-line no-constant-condition
// Create possible solution string from challenge string + nonce.
@@ -38,17 +38,19 @@ let compute = async function(seedStr, challengeStr) {
return nonce;
}
- // Iter.
- nonce++;
+ // Iter nonce.
+ nonce += iter;
}
};
onmessage = async function(e) {
- console.log('worker started'); // eslint-disable-line no-console
+ const thread = e.data.thread;
+ const threads = e.data.threads;
+ console.log("worker started:", thread); // eslint-disable-line no-console
- // Compute nonce value that produces 'challenge' for seed.
- let nonce = await compute(e.data.seed, e.data.challenge);
+ // Compute nonce value that produces 'challenge', for our allotted thread.
+ let nonce = await compute(e.data.seed, e.data.challenge, thread, threads);
- // Post the solution nonce back to caller.
- postMessage({ nonce: nonce, done: true });
+ // Post the solution nonce back to caller with thread no.
+ postMessage({ nonce: nonce, done: true, thread: thread });
};