Skip to content

perf(swift-sdk): gate SPV progress polling on inequality#3555

Merged
QuantumExplorer merged 1 commit into
v3.1-devfrom
claude/compassionate-bell-a57552
Apr 28, 2026
Merged

perf(swift-sdk): gate SPV progress polling on inequality#3555
QuantumExplorer merged 1 commit into
v3.1-devfrom
claude/compassionate-bell-a57552

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Apr 28, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

After leaving SwiftExampleApp running overnight the user observed it sitting at 729 MB memory and 98% CPU. Investigation traced the runaway to the 1 Hz SPV-progress polling task in PlatformWalletManager.

The poller reassigned @Published spvProgress and @Published platformAddressSyncIsSyncing on every tick regardless of whether the values had actually changed. Because PlatformSpvSyncProgress and PlatformSpvSubProgress were Sendable but not Equatable, each assignment unconditionally fired objectWillChange — forcing every observing view (the sync screens, the memory explorer, GlobalSyncIndicator) to re-evaluate body once per second forever. Over ~12 hours that's ~43,200 SwiftUI invalidations; the attribute graph and diffing caches accreted, and the loop re-emitted onto the main thread every second forever, even after sync had long settled.

What was done?

  • Added Equatable conformance to PlatformSpvSubProgress and PlatformSpvSyncProgress (all members were already Equatable — just synthesised conformance).
  • Gated the two @Published assignments in startProgressPolling() on inequality so identical snapshots no longer republish.
  • Added a comment on the polling function explaining why the gate exists, so a future hand doesn't accidentally undo it.

The polling loop itself, its cancellation in deinit, and the FFI calls are unchanged.

How Has This Been Tested?

  • xcodebuild -project SwiftExampleApp/SwiftExampleApp.xcodeproj -scheme SwiftExampleApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.6,arch=arm64' build succeeds.
  • Manual verification of the regression itself (run overnight, watch CPU/memory) is suggested as a follow-up — the static read is already pretty conclusive but a confirmation trace would be worth banking. Instruments → Time Profiler should show the platform_wallet_manager_sync_progress stack drop out of the hot path once sync settles.

Breaking Changes

None. Equatable is an additive conformance on public types; existing call sites that didn't compare these structs continue to compile unchanged.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

Summary by CodeRabbit

  • Performance
    • Optimized wallet synchronization polling to reduce redundant property updates and minimize unnecessary UI refresh cycles, improving overall app responsiveness during sync operations.

The 1 Hz progress poller in `PlatformWalletManager` reassigned `@Published
spvProgress` and `platformAddressSyncIsSyncing` every tick regardless of
whether the values had actually changed. Because `PlatformSpvSyncProgress`
was `Sendable` but not `Equatable`, every assignment fired
`objectWillChange`, forcing every observing view (sync screens, memory
explorer, global indicator) to re-evaluate `body` once per second forever
— accreting SwiftUI attribute-graph state and burning CPU long after sync
settled. After ~12 hours the example app was sitting at 729 MB / 98% CPU.

Adds `Equatable` conformance to `PlatformSpvSubProgress` and
`PlatformSpvSyncProgress` and gates each assignment on inequality so
identical snapshots are dropped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added this to the v3.1.0 milestone Apr 28, 2026
@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88c45451-f417-4fe7-9009-fcfc81977348

📥 Commits

Reviewing files that changed from the base of the PR and between 844edba and 78346ce.

📒 Files selected for processing (2)
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift

📝 Walkthrough

Walkthrough

The changes optimize polling behavior by adding Equatable conformance to progress tracking structs and implementing conditional property updates in the polling loop. This prevents redundant SwiftUI observer re-evaluations when progress values remain unchanged between polling iterations.

Changes

Cohort / File(s) Summary
SPV Progress Struct Conformance
PlatformWalletManagerSPV.swift
Added Equatable conformance to PlatformSpvSubProgress and PlatformSpvSyncProgress structs to enable value comparison between instances.
Polling Loop Optimization
PlatformWalletManager.swift
Modified startProgressPolling method to conditionally assign @Published properties (spvProgress, platformAddressSyncIsSyncing) only when newly fetched values differ from currently stored ones, eliminating redundant SwiftUI re-evaluations.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A rabbit hops with joy,
No needless updates to employ,
Equatable now, we compare with care,
SwiftUI breathes lighter air!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'perf(swift-sdk): gate SPV progress polling on inequality' accurately and concisely summarizes the main performance optimization change—adding inequality checks to prevent redundant @Published property reassignments in the SPV progress polling loop.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/compassionate-bell-a57552

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@thepastaclaw

thepastaclaw commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator

Review Gate

Commit: 78346ced

  • Debounce: 28m ago (need 30m)

  • CI checks: builds passed, 0/2 tests passed

  • CodeRabbit review: comment found

  • Off-peak hours: off-peak (12:59 AM PT Tuesday)

  • Run review now (check to override)

@github-actions

Copy link
Copy Markdown
Contributor

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "c9c002c3def410e95ca2f5967d5d53db2bd11d9fb1491d331aaf634f2cadaa78"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self Reviewed

@QuantumExplorer QuantumExplorer merged commit 22114f7 into v3.1-dev Apr 28, 2026
37 checks passed
@QuantumExplorer QuantumExplorer deleted the claude/compassionate-bell-a57552 branch April 28, 2026 07:57
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.

2 participants