Disabling Timer Coalescing in OSX for a given process
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Timer coalescing is a macOS power-saving feature that groups nearby timer firings together, reducing CPU wake-ups and saving battery. Instead of waking the CPU for each individual timer, the system delays timers slightly to fire them in batches. This is great for battery life but problematic for latency-sensitive applications like audio processing, real-time data collection, or benchmarking tools that need precise timer resolution. You can disable it per-process using QoS classes, mach_timebase APIs, or by launching with specific arguments.
How Timer Coalescing Works
Without coalescing:
With coalescing (default):
macOS applies a "leeway" to each timer. The system can delay the timer by up to the leeway amount to align it with other timers. The default leeway depends on the timer type and QoS class.
Method 1: Set QoS Class (Recommended)
The Quality of Service class controls timer coalescing behavior. Higher QoS classes get less coalescing:
QoS classes and their coalescing behavior:
| QoS Class | Timer Leeway | Use Case |
.userInteractive | Minimal (~0ms) | UI animations, audio |
.userInitiated | Low (~1ms) | User-triggered tasks |
.default | Medium (~5ms) | General work |
.utility | High (~10ms) | Long-running tasks |
.background | Maximum (~100ms+) | Maintenance, backups |
Method 2: dispatch_source Timer with Zero Leeway
The .strict flag tells the system this timer should not be coalesced.
Method 3: NSTimer with Tolerance
Setting tolerance = 0 is a request, not a guarantee. The system may still apply minimal coalescing.
Method 4: Mach Absolute Time (Lowest Level)
For the highest precision, use Mach APIs directly:
Real-time threads get the highest scheduling priority and effectively bypass timer coalescing.
Method 5: Launch with caffeinate
For quick testing, wrap your process with caffeinate:
caffeinate raises the process priority and reduces power management interference, indirectly reducing timer coalescing.
Checking Timer Coalescing Status
Disabling System-Wide (Not Recommended)
Common Pitfalls
- Battery drain: Disabling timer coalescing increases CPU wake-ups significantly. A MacBook might see 20-30% more power usage. Only disable for processes that genuinely need sub-millisecond precision.
- Not using the right QoS: Setting
.userInteractiveon a background task wastes power and starves other processes. Match QoS to actual requirements. - Tolerance vs leeway confusion:
NSTimer.toleranceanddispatch_sourceleeway both control coalescing but through different APIs. Setting one does not affect the other. - Expecting microsecond precision: Even with coalescing disabled, macOS is not a real-time OS. Thread scheduling, interrupts, and other system activity introduce jitter. For true real-time, use a dedicated audio or I/O thread with
THREAD_TIME_CONSTRAINT_POLICY. - SIP restrictions: On modern macOS with System Integrity Protection enabled, some kernel-level timer settings cannot be modified. Use QoS and dispatch source APIs instead.
Summary
- Timer coalescing groups timer firings to save power — adds small delays to timers
- Use
QOS_CLASS_USER_INTERACTIVEto minimize coalescing for a thread - Use
DispatchSourcewith.strictflag and zero leeway for precise timers - Set
NSTimer.tolerance = 0to request no coalescing - Use Mach real-time thread policies for the highest precision
- Only disable coalescing for genuinely latency-sensitive work — it significantly impacts battery life

