Skip to content

Fix 232ms UI hang in call duration timer #836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

sampepose
Copy link

🔗 Issue Links

N/A - Performance improvement identified through profiling

🎯 Goal

Fix a 232ms UI hang that occurs every second during active calls, caused by expensive Swift runtime protocol conformance checking when accessing @Published properties in a timer callback.

📝 Summary

  • Eliminated 232ms/second UI hang by caching startedAt value to avoid @Published property access
  • Moved duration timer to background queue using DispatchSourceTimer instead of Foundation.Timer
  • Removed unnecessary @objc updateDuration() method by calculating duration inline
  • Zero impact on functionality - duration updates work exactly the same, just more efficiently

🛠 Implementation

The issue was discovered through Instruments profiling, which showed swift_dynamicCast and protocol conformance checking taking 232ms when the duration timer accessed the @Published var startedAt property.

Root cause: Every second, the timer would access startedAt through the @Published property wrapper, triggering expensive Swift runtime checks for protocol conformances.

Screenshot 2025-06-06 at 11 25 33 AM

Solution:

  1. Cache the value: Added _cachedStartedAt to store the date without going through @Published
  2. Background timer: Switched from Foundation.Timer (main thread) to DispatchSourceTimer (background queue)
  3. Minimal main thread work: Only the final duration update happens on main thread

This approach eliminates both the protocol conformance overhead AND keeps the timer work off the main thread.

🎨 Showcase

Before After
232ms hang every second during calls Smooth 60fps during calls
Timer blocks main thread Timer runs on background queue
@Published access in hot path Cached value access

🧪 Manual Testing Notes

  1. Start a video call
  2. Verify the call duration timer updates every second
  3. Monitor performance with Instruments - no more periodic hangs
  4. Verify timer stops correctly when call ends
  5. Test timer behavior during reconnection scenarios

☑️ Contributor Checklist

@sampepose sampepose requested a review from a team as a code owner June 6, 2025 15:39
@ipavlidakis
Copy link
Contributor

Hey @sampepose, thank you for this PR. We are currently in the process of resolving many performance issues (you can take see a sneak peek in the open PRs).

We are now in a state where we have resolved all the hungs and for that reason I'm not going to accept this PR.

I'm going to keep open though as I reminder to check again once the changes have been merged.

Thanks,
Ilias

@sampepose
Copy link
Author

Great, I see this was addressed in #825!

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