diff --git a/.jules/bolt.md b/.jules/bolt.md index b08b203a..c5fe5de2 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -4,3 +4,7 @@ ## 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-30 - Optimize buildWeekdayTimeline date loop +**Learning:** Repeatedly parsing date strings and creating new Date objects inside tight rendering loops (like Gantt chart timeline generation) causes significant allocation overhead and slows down O(N) operations. +**Action:** Mutate a single Date object and use native getUTCDay()/setUTCDate() methods instead of repeatedly passing strings back and forth to formatting helpers. diff --git a/app.js b/app.js index b8c62279..0aaf9e9a 100644 --- a/app.js +++ b/app.js @@ -2414,17 +2414,21 @@ function createGanttChartTable(weeks, weekdays, totalWidth) { function buildWeekdayTimeline(minDate, maxDate) { const days = []; - let cursor = getMonday(minDate); - const endBoundary = getFriday(maxDate); - // ⚡ Bolt: Use direct string comparison for cursor loop since both are generated valid dates. - while (cursor <= endBoundary) { - if (!isWeekend(cursor)) { + const startMs = dateStringToUtcMs(getMonday(minDate)); + const endMs = dateStringToUtcMs(getFriday(maxDate)); + + // ⚡ Bolt: Mutate a single Date object to avoid expensive parsing/formatting in O(N) loop + const cursorDate = new Date(startMs); + while (cursorDate.getTime() <= endMs) { + const dayOfWeek = cursorDate.getUTCDay(); + if (dayOfWeek !== 0 && dayOfWeek !== 6) { + const dateStr = formatDateInput(cursorDate); days.push({ - date: cursor, - dayLabel: cursor.slice(8, 10) + date: dateStr, + dayLabel: dateStr.slice(8, 10) }); } - cursor = addDays(cursor, 1); + cursorDate.setUTCDate(cursorDate.getUTCDate() + 1); } return days; }