Skip to content

[@mantine/schedule] Fix O(n²) date re-parsing in WeekView event positioning#9075

Open
eh-bartosz-lewandowski wants to merge 1 commit into
mantinedev:masterfrom
eh-bartosz-lewandowski:fix/weekview-positioning-perf
Open

[@mantine/schedule] Fix O(n²) date re-parsing in WeekView event positioning#9075
eh-bartosz-lewandowski wants to merge 1 commit into
mantinedev:masterfrom
eh-bartosz-lewandowski:fix/weekview-positioning-perf

Conversation

@eh-bartosz-lewandowski

Copy link
Copy Markdown

What & why

getWeekPositionedEvents assigns overlapping events to columns in an O(n²) pass, and on every pairwise comparison it re-parsed dates with dayjs — isEventsOverlap parsed all four start/end strings, and columnHasConflict recomputed each event's all-day flag by calling isAllDayEvent across every weekday. At ~1,500 events that is ~1.3M dayjs parses ≈ 9.6s to lay out one week, and it degrades quadratically.

Change

Parse each date once instead of on every comparison:

  • Cache each event's { start, end } timestamps in a WeakMap in is-events-overlap (also benefits DayView / ResourcesDayView, which use the same util).
  • Compute the all-day flag once when an event is placed into a column and store it as ColumnEvent { event, allDay }, so columnHasConflict reads the precomputed flag instead of recomputing isAllDayEvent.

This is a pure memoization / precompute — layout output is unchanged. The stored per-event all-day flag is equivalent to the original per-comparison recompute: isAllDayEvent is true only on the event's own start day, which is always within the event's covered days.

Result

Positioning 1,500 events: ~9,600ms → ~125ms (~77×); a typical week lays out in a few ms.

Notes

The WeakMap assumes events are immutable value objects (matching the library's callback-based update model). Mutating an existing event's start/end in place while reusing the same object reference across positioning passes would serve cached timestamps — not a concern for normal usage.

Tests

Updated find-available-column unit tests for the new column shape.

…ioning

Positioning compared every event against every other and re-parsed dates with
dayjs on each comparison — dominated by columnHasConflict recomputing
isAllDayEvent across all week days per pair (~1.3M dayjs parses, ~9.6s at 1500
events).

Cache parsed start/end timestamps per event via a WeakMap in is-events-overlap,
and precompute the all-day flag once when an event is placed into a column
(ColumnEvent). Positioning drops from ~9600ms to ~125ms at 1500 events with
identical output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant