From 2dccc50ec069c2ea0ff3c1e2ad7f635744c0e8eb Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 28 Aug 2026 13:47:38 +0000 Subject: [PATCH 1/2] perf: replace reduce/forEach and Map caching with for loops and Int32Array in computeTaskMetrics Optimizes computeTaskMetrics in app.js by stripping out the JS callback overhead and garbage collection from Array.prototype.reduce and forEach. Replaces the slow Map hash-lookup for caching durationDays with a fast Int32Array indexed by the task array position. --- .jules/bolt.md | 3 +++ app.js | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index b08b203a..f226afef 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -4,3 +4,6 @@ ## 2026-07-12 - Optimize renderTaskRow DOM allocations **Learning:** Caching unattached template nodes and instantiating them via `.cloneNode(false)` reduces DOM instantiation overhead in O(N) render loops significantly. **Action:** Apply this optimization to other hot-path rendering elements such as rows, cells, and stack containers. +## 2026-07-12 - Replacing Array callbacks and Map with for loops and Int32Array +**Learning:** For high-performance O(N) loops in JavaScript, replacing `Array.prototype.reduce`/`forEach` and `Map` caching with standard `for` loops and typed arrays (e.g., `Int32Array`) eliminates JS engine callback allocation, garbage collection, and hash-lookup overhead. +**Action:** Apply standard `for` loops and typed arrays for numerical caches instead of higher-order array methods and Maps on hot paths or large datasets to ensure maximum performance. diff --git a/app.js b/app.js index a04aae71..e27e4e5a 100644 --- a/app.js +++ b/app.js @@ -1370,21 +1370,26 @@ function validateDateRange(startLabel, startValue, endLabel, endValue, errors) { } function computeTaskMetrics() { - // ⚡ Bolt: Cache durationDays during total calculation to avoid recalculating for every task - const durationCache = new Map(); - const totalDays = state.tasks.reduce((sum, task) => { + // ⚡ Bolt: Optimize with standard for loops and Int32Array to avoid JS callback overhead, GC overhead and hash lookups for duration tracking + const tasksLen = state.tasks.length; + const durationCache = new Int32Array(tasksLen); + let totalDays = 0; + + for (let i = 0; i < tasksLen; i++) { + const task = state.tasks[i]; const duration = calculateDurationDays(task.plannedStartDate, task.plannedEndDate); - durationCache.set(task.id, duration); - return sum + duration; - }, 0); + durationCache[i] = duration; + totalDays += duration; + } const baseDate = state.baseDate; const byTask = new Map(); let totalWeightedPlannedRatio = 0; let totalWeightedActualRatio = 0; - state.tasks.forEach((task) => { - const durationDays = durationCache.get(task.id); + for (let i = 0; i < tasksLen; i++) { + const task = state.tasks[i]; + const durationDays = durationCache[i]; const weightRatio = totalDays > 0 ? durationDays / totalDays : 0; const plannedProgressRatio = calculatePlannedProgressRatio(baseDate, task.plannedStartDate, task.plannedEndDate, durationDays); const actualProgressRatio = (ACTUAL_PROGRESS_MAP[task.actualProgressStatus] || 0) / 100; @@ -1408,7 +1413,7 @@ function computeTaskMetrics() { plannedDateWarning, actualDateWarning }); - }); + } return { totalDays, From d0141077d3bb790786520efa3d115d4dd2ce70bf Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 28 Aug 2026 14:03:19 +0000 Subject: [PATCH 2/2] perf: replace Int32Array with Float64Array for numeric safety Replaces Int32Array with Float64Array in computeTaskMetrics to ensure duration arithmetic does not suffer from silent truncation if values ever become fractional or NaN. Fixes the previous type coercion logic flaw. --- .jules/bolt.md | 3 +++ app.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index f226afef..23d11642 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -7,3 +7,6 @@ ## 2026-07-12 - Replacing Array callbacks and Map with for loops and Int32Array **Learning:** For high-performance O(N) loops in JavaScript, replacing `Array.prototype.reduce`/`forEach` and `Map` caching with standard `for` loops and typed arrays (e.g., `Int32Array`) eliminates JS engine callback allocation, garbage collection, and hash-lookup overhead. **Action:** Apply standard `for` loops and typed arrays for numerical caches instead of higher-order array methods and Maps on hot paths or large datasets to ensure maximum performance. +## 2026-08-28 - Float64Array over Int32Array for Numeric Safety +**Learning:** Using `Int32Array` in JavaScript for caching standard numeric values can introduce silent truncation errors if the values ever become fractional or `NaN`, which breaks math operations down the line. +**Action:** Default to `Float64Array` or a standard `Array(length)` when caching calculated numbers unless the type is strictly known and guaranteed to be an integer. diff --git a/app.js b/app.js index e27e4e5a..8a0d8044 100644 --- a/app.js +++ b/app.js @@ -1370,9 +1370,9 @@ function validateDateRange(startLabel, startValue, endLabel, endValue, errors) { } function computeTaskMetrics() { - // ⚡ Bolt: Optimize with standard for loops and Int32Array to avoid JS callback overhead, GC overhead and hash lookups for duration tracking + // ⚡ Bolt: Optimize with standard for loops and Float64Array to avoid JS callback overhead, GC overhead and hash lookups for duration tracking const tasksLen = state.tasks.length; - const durationCache = new Int32Array(tasksLen); + const durationCache = new Float64Array(tasksLen); let totalDays = 0; for (let i = 0; i < tasksLen; i++) {