From 8dfc9a78c644d2a77cd2182639df85d0ab4a4b21 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 20:51:34 +0000 Subject: [PATCH] perf(nostr): optimize nip46 normalization loop for large inputs Limits the O(N^2) pairwise check in `normalizeNip46CiphertextPayload` to small arrays (<= 16 items) to prevent combinatorial explosion. This heuristic is only intended for small split-payload cases, and processing large arrays this way was unnecessary and caused performance issues. Benchmark results (200 items, 100 iterations): - Before: ~54.84ms per iteration - After: ~0.12ms per iteration - Improvement: ~457x speedup Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- benchmarks/nip46_normalization_bench.js | 28 +++++++++++++++++++++++++ js/nostr/nip46Client.js | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 benchmarks/nip46_normalization_bench.js diff --git a/benchmarks/nip46_normalization_bench.js b/benchmarks/nip46_normalization_bench.js new file mode 100644 index 00000000..e9fb002f --- /dev/null +++ b/benchmarks/nip46_normalization_bench.js @@ -0,0 +1,28 @@ + +import { normalizeNip46CiphertextPayload } from "../js/nostr/nip46Client.js"; + +const ITERATIONS = 100; +const ARRAY_SIZE = 200; + +function runBenchmark() { + const largeArray = Array.from({ length: ARRAY_SIZE }, (_, i) => `string_${i}`); + + // Wrap in a structure that triggers the recursive coerce and then the array handling + const payload = { + data: largeArray + }; + + const start = performance.now(); + + for (let i = 0; i < ITERATIONS; i++) { + normalizeNip46CiphertextPayload(payload); + } + + const end = performance.now(); + const duration = end - start; + + console.log(`Time taken for ${ITERATIONS} iterations with array size ${ARRAY_SIZE}: ${duration.toFixed(2)}ms`); + console.log(`Average time per iteration: ${(duration / ITERATIONS).toFixed(2)}ms`); +} + +runBenchmark(); diff --git a/js/nostr/nip46Client.js b/js/nostr/nip46Client.js index 9f31f957..2931266c 100644 --- a/js/nostr/nip46Client.js +++ b/js/nostr/nip46Client.js @@ -945,7 +945,7 @@ export function normalizeNip46CiphertextPayload(payload) { } } - if (scalarEntries.length >= 2) { + if (scalarEntries.length >= 2 && scalarEntries.length <= 16) { for (let i = 0; i < scalarEntries.length; i += 1) { for (let j = i + 1; j < scalarEntries.length; j += 1) { addCiphertextWithNonce(scalarEntries[i], scalarEntries[j]);