diff --git a/.jules/bolt.md b/.jules/bolt.md index 8aef41f..54476e6 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -8,3 +8,7 @@ ## 2024-05-24 - Pre-compile RegExp in nested loops **Learning:** Instantiating `new RegExp()` inside nested array methods like `.filter` and `.some` creates a severe O(N*M) performance bottleneck, especially when matching two large lists (e.g., documented tests vs. actual test files). **Action:** Always pre-compile regular expressions and derived strings into an array of "matcher" objects outside of the loop before iterating, which shifts the instantiation cost from O(N*M) to O(N). + +## 2024-05-25 - O(N*M) Array.find bottlenecks +**Learning:** Using `Array.find` inside nested loops to match entity properties (e.g., schemas and fields) causes an $O(N^2)$ algorithmic bottleneck, especially noticeable when parsing large documents like OpenAPI specifications. +**Action:** Always precompute a `Map` of the target array for $O(1)$ lookups based on the identifier key before entering the nested loops. diff --git a/cli/scanners/schemas.mjs b/cli/scanners/schemas.mjs index 2064b2a..0db4d67 100644 --- a/cli/scanners/schemas.mjs +++ b/cli/scanners/schemas.mjs @@ -713,11 +713,16 @@ function scanRailsModels(dir) { function extractOpenAPIRelationships(schemas) { const relationships = []; + + // PERFORMANCE OPTIMIZATION: Precompute an O(1) Map lookup of lowercased schema names + // to avoid O(N*M) array find lookups during the nested schema/field loops. + const schemaMap = new Map(schemas.map(s => [s.name.toLowerCase(), s])); + for (const schema of schemas) { for (const field of schema.fields) { if (field.type !== 'string' && field.type !== 'number' && field.type !== 'boolean' && field.type !== 'integer') { // Likely a reference to another schema - const target = schemas.find(s => s.name.toLowerCase() === field.type.toLowerCase()); + const target = schemaMap.get(field.type.toLowerCase()); if (target) { relationships.push({ from: schema.name,