⚡ Optimize string lowercasing in registry loop

* Extracted multiple `.toLowerCase()` calls on identical characters during unit concatenation and phrase generation
* Cached the lowercased strings in parallel arrays during `csPhrases` initialization
* Preserves all functional string behavior

Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-07-08 10:25:58 +00:00
parent 1b61ec35cc
commit ecda72a9a7
2 changed files with 19 additions and 4 deletions

3
.jules/bolt.md Normal file
View file

@ -0,0 +1,3 @@
## 2025-07-08 - Optimize string lowercasing in nested loops
**Learning:** In nested loops generating combinations of strings (like symbols and prefixes), repeated calls to `.toLowerCase()` on the concatenated string create an overhead. Caching the lowercase strings during concatenation using parallel arrays is an effective strategy to eliminate redundant operations, but extracting the loop variable correctly when restructuring the iteration pattern is crucial to maintain compile safety.
**Action:** Prioritize lowercasing loop variables at the earliest possible stage and ensure that when caching results in arrays, corresponding iteration logic consistently references the indexed values correctly.

View file

@ -314,12 +314,24 @@ function registerUnits(reg: Registry): LengthPhrase[] {
};
const phrases: string[] = [];
const csPhrases: string[] = [];
const csPhrasesLower: string[] = [];
if (d.id === "bit") {
// no "kb" for bits — bare *b symbols mean bytes (common expectation)
csPhrases.push(`${pSym}bit`);
const bitPhrase = `${pSym}bit`;
csPhrases.push(bitPhrase);
csPhrasesLower.push(bitPhrase.toLowerCase());
} else {
// symbol compositions in every locale: "km" and "км"
for (const ps of pSymsAll) for (const us of symbolsAll) csPhrases.push(ps + us);
const pSymsAllLower = pSymsAll.map((s) => s.toLowerCase());
const symbolsAllLower = symbolsAll.map((s) => s.toLowerCase());
for (let i = 0; i < pSymsAll.length; i++) {
const ps = pSymsAll[i];
const psL = pSymsAllLower[i];
for (let j = 0; j < symbolsAll.length; j++) {
csPhrases.push(ps + symbolsAll[j]);
csPhrasesLower.push(psL + symbolsAllLower[j]);
}
}
}
for (const pw of pWords) for (const wv of wordVariants) phrases.push(pw + wv);
if (d.id === "byte" && pSym) {
@ -331,8 +343,8 @@ function registerUnits(reg: Registry): LengthPhrase[] {
for (const ph of phrases) reg.addPhrase(ph, { t: "unit", unit: pUnit }, { caseSensitive: false });
// collect unambiguous lowercase forms: "KM"/"Km" should still mean km,
// while "mm"/"Mm" stay strict (milli vs mega)
for (const ph of csPhrases) {
const lower = ph.toLowerCase();
for (let i = 0; i < csPhrasesLower.length; i++) {
const lower = csPhrasesLower[i];
const prev = lenientSym.get(lower);
if (prev === undefined) lenientSym.set(lower, pUnit);
else if (prev && prev.id !== pUnit.id) lenientSym.set(lower, null);