Skip to content

Perf/reduce main thread load#29

Open
iamkishann wants to merge 2 commits into
b-nnett:mainfrom
iamkishann:perf/reduce-main-thread-load
Open

Perf/reduce main thread load#29
iamkishann wants to merge 2 commits into
b-nnett:mainfrom
iamkishann:perf/reduce-main-thread-load

Conversation

@iamkishann

Copy link
Copy Markdown

ActivitySessionModel.swift — Keep 60 Hz sampling intact, but decouple it from SwiftUI publishes. Each tick now writes to private backing stores (_elapsed, _zoneDurations, etc.) and only flushes to the @published properties at 4 Hz (250 ms). pause() and end() always flush immediately so the UI reflects the final state. Result: 60 re-renders/sec → 4 re-renders/sec during an active session.

HomeDashboardView.swift — healthStore.landingSnapshots(…) was being called 9× per body render (once per landingSnapshot(for:), scoreSnapshots, scorePickerSnapshots call site). Now computed once at the top of body and threaded through as a parameter.

GooseAppModel+Lifecycle.swift — applyHeartRateTimelineSnapshot fires every 1 second and was unconditionally writing to heartRateHourlyRanges, triggering objectWillChange on GooseAppModel (and a full re-render of every @EnvironmentObject observer) even when the data hadn't changed. Added equality guard; same for heartRateStorageStatus.

GooseAppModel+PacketPublishing.swift — activityDetectionStatus (set on every movement packet) and movementPacketValidationStatus (set during validation runs) now skip the @published assignment when the new value equals the current one, suppressing unnecessary broadcasts.

GooseMessageStore.swift — Replaced messages.insert(contentsOf: pendingMessages.reversed(), at: 0) with array concatenation to avoid a buffer-copy churn on every 500 ms flush.

iamkishann and others added 2 commits June 7, 2026 12:54
…nt publishes

- ActivitySessionModel: lower workout timer from 60 Hz to 1 Hz; each tick
  updates 4+ @published properties, so 60 Hz was driving 60 SwiftUI re-renders
  per second on the main thread for the duration of any activity session.
  1 Hz is sufficient precision for a stopwatch display; timer tolerance raised
  from 2 ms to 50 ms to let the system coalesce timer firings.

- HomeDashboardView: compute landingSnapshots (→ healthStore.landingSnapshots)
  once per body pass instead of 9 times. Previously every call to
  landingSnapshot(for:), homeSnapshot(for:), scoreSnapshots, and
  scorePickerSnapshots each triggered a separate full evaluation of the
  expensive healthStore.landingSnapshots(…) call.

- GooseAppModel: add equality guards on applyHeartRateTimelineSnapshot so
  heartRateHourlyRanges (updated at 1 Hz by the pipeline) only fires
  objectWillChange when the data actually changes, preventing unnecessary
  full-view re-renders of all GooseAppModel @EnvironmentObject observers.

- GooseAppModel: equality guard on activityDetectionStatus (set on every
  movement packet) and movementPacketValidationStatus to suppress redundant
  objectWillChange publications when the string value is unchanged.

- GooseMessageStore: replace O(n) insert-at-0 with array concatenation to
  avoid unnecessary buffer-copy churn on every 500 ms message flush.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ishes

The 60 Hz timer is intentional and needed for accurate HR-zone accounting and
motion-intensity tracking for athletes. The problem was that every tick also
wrote to @published properties, driving a SwiftUI re-render on every sample.

Fix: accumulate all metrics (elapsed, zoneDurations, averageHeartRate,
maxHeartRate) into private backing stores at full 60 Hz, and flush to the
@published properties at 4 Hz (every 250 ms). SwiftUI coalesces the four
property assignments inside flushToUI into a single re-render because they
happen synchronously in the same runloop turn.

State-transition calls (pause, end) always call flushToUI immediately so the
UI reflects the final sample before the session stops.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tigercraft4 referenced this pull request in tigercraft4/goose Jun 9, 2026
@tigercraft4 tigercraft4 mentioned this pull request Jun 9, 2026
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