Skip to content

Fix 232ms UI hang in call duration timer #836

New issue

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

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

Already on GitHub? # 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!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants