summaryrefslogtreecommitdiff
path: root/web/source/nollamas/index.js
diff options
context:
space:
mode:
authorLibravatar kim <grufwub@gmail.com>2025-05-31 13:45:32 +0200
committerLibravatar tobi <kipvandenbos@noreply.codeberg.org>2025-05-31 13:45:32 +0200
commita82d574acc88130578e3c066243a487344f29979 (patch)
tree3af164ed91182844c3358d6b1ce85254bcd2382a /web/source/nollamas/index.js
parent[chore] Upgrade to SQLite 3.50 (#4218) (diff)
downloadgotosocial-a82d574acc88130578e3c066243a487344f29979.tar.xz
[feature] make client-side nonce calculation multi-threaded (#4219)
# Description Thank you in part to f0x for nerd-sniping me into banging this together :p ## Checklist - [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md). - [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat. - [x] I/we have not leveraged AI to create the proposed changes. - [x] I/we have performed a self-review of added code. - [x] I/we have written code that is legible and maintainable by others. - [x] I/we have commented the added code, particularly in hard-to-understand areas. - [ ] I/we have made any necessary changes to documentation. - [ ] I/we have added tests that cover new code. - [x] I/we have run tests and they pass locally with the changes. - [x] I/we have run `go fmt ./...` and `golangci-lint run`. Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4219 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'web/source/nollamas/index.js')
-rw-r--r--web/source/nollamas/index.js118
1 files changed, 76 insertions, 42 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);
+ }
+ };
+ }
});