From c6f4988ee23f1a83b97e1b72bb5ab56ddb123795 Mon Sep 17 00:00:00 2001 From: LewdLeah Date: Thu, 28 Aug 2025 15:00:25 -0400 Subject: [PATCH] Update library.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4x time performance improvement for Auto-Cards, in cases where formatTitle may be called upwards of tens of thousands of times. You know things are bad when implementing memoization proves to be easier than fixing the call stack 💀 --- src/library.js | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/library.js b/src/library.js index 66dd07b..779a0b6 100644 --- a/src/library.js +++ b/src/library.js @@ -1,4 +1,5 @@ // Your "Library" tab should look like this + /* Auto-Cards Made by LewdLeah on May 21, 2025 @@ -494,6 +495,7 @@ function AutoCards(inHook, inText, inStop) { const CODOMAIN = new Const().declare(); // Transient sets for high-performance lookup const [used, bans, auto, forenames, surnames] = Array.from({length: 5}, () => new Set()); + const memoized = new Map(); // Holds a reference to the data card singleton, remains unassigned unless required let data = null; // Validate globalThis.text @@ -5488,11 +5490,29 @@ function AutoCards(inHook, inText, inStop) { return String.fromCharCode(...arr.map(n => Math.sqrt(n / 33))); } function formatTitle(title) { + const input = title; + let useMemo = false; + if ( + (AC.database.titles.used.length === 1) + && (AC.database.titles.used[0] === ("%@%")) + && [used, forenames, surnames].every(nameset => ( + (nameset.size === 1) + && nameset.has("%@%") + )) + ) { + const pair = memoized.get(input); + if (pair !== undefined) { + if (50000 < memoized.size) { + memoized.delete(input); + memoized.set(input, pair); + } + return O.f({newTitle: pair[0], newKey: pair[1]}); + } + useMemo = true; + } title = title.trim(); - const failureCase = O.f({newTitle: "", newKey: ""}); if (short()) { - // This is an abundantly called function, return as early as possible to ensure superior performance - return failureCase; + return end(); } title = (title // Begone! @@ -5514,7 +5534,7 @@ function AutoCards(inHook, inText, inStop) { .replace(/^-+\s*/, "").replace(/\s*-+$/, "") ); if (short()) { - return failureCase; + return end(); } // Special-cased words const minorWordsJoin = Words.minor.join("|"); @@ -5523,7 +5543,7 @@ function AutoCards(inHook, inText, inStop) { // Ensure the title is not bounded by any outer minor words title = enforceBoundaryCondition(title); if (short()) { - return failureCase; + return end(); } // Ensure interior minor words are lowercase and excise all interior honorifics/abbreviations const honorAbbrevsKiller = new RegExp("(?:^|\\s|-|\\/)(?:" + ( @@ -5546,7 +5566,7 @@ function AutoCards(inHook, inText, inStop) { .trim() ); if (short()) { - return failureCase; + return end(); } let titleWords = title.split(" "); while ((2 < title.length) && (98 < title.length) && (1 < titleWords.length)) { @@ -5559,14 +5579,14 @@ function AutoCards(inHook, inText, inStop) { } } if (isUsedOrBanned(title) || isNamed(title)) { - return failureCase; + return end(); } // Procedurally generated story card trigger keywords exclude certain words and patterns which are otherwise permitted in titles let key = title; const peerage = new Set(Words.peerage); if (titleWords.some(word => ((word === "the") || peerage.has(word.toLowerCase())))) { if (titleWords.length < 2) { - return failureCase; + return end(); } key = enforceBoundaryCondition( titleWords.filter(word => !peerage.has(word.toLowerCase())).join(" ") @@ -5575,7 +5595,7 @@ function AutoCards(inHook, inText, inStop) { key = enforceBoundaryCondition(key.split(" the ")[0]); } if (isUsedOrBanned(key)) { - return failureCase; + return end(); } } function short() { @@ -5590,7 +5610,16 @@ function AutoCards(inHook, inText, inStop) { } return str; } - return O.f({newTitle: title, newKey: key}); + function end(newTitle = "", newKey = "") { + if (useMemo) { + memoized.set(input, [newTitle, newKey]); + if (55000 < memoized.size) { + memoized.delete(memoized.keys().next().value); + } + } + return O.f({newTitle, newKey}); + } + return end(title, key); } // I really hate english grammar function checkPlurals(title, predicate) {