Swift's native Clocks are inefficient

Swift’s new native `Clock` APIs are being criticized for adding hundreds of nanoseconds of overhead per call compared to lower-level timers like `mach_absolute_time` or `clock_gettime`, which can matter in tight loops or high-frequency operations. Commenters debate whether this inefficiency stems from poor abstraction design or intentional mitigation of timing-based attacks and device fingerprinting, noting that Apple now treats precise timers as “sensitive” APIs. The conversation also touches on Swift’s standard library being tied to OS versions, the trade-offs of Apple’s security and app review model, and practical alternatives developers currently use for high-precision timing.

Clarifying the benchmark results

  • Some readers misread the table as 19–30 ms per call; others point out it’s the median time for 1,000,000 iterations, so ~19–30 ns per call for Date/NSDate.
  • Swift’s new Clock types are much slower than low-level options, but still in the hundreds of nanoseconds per call, not milliseconds.

Swift timing APIs vs other ecosystems

  • Developers coming from C# note that Stopwatch is simple and precise, whereas Swift has many overlapping options (Clock, DispatchTime, Date, etc.), which feels confusing and sometimes inefficient.
  • Suggestions include using CACurrentMediaTime, Date, or directly clock_gettime/clock_gettime_nsec_np for performance, though each has trade-offs (dependencies, non-monotonicity).

Platform constraints and standard library versioning

  • Questions arise why even a protocol like Clock is documented as iOS 16+.
  • Explanation: Swift’s standard library is now shipped with the OS as dynamic libraries; you’re tied to the OS’s Swift version. Apple rarely backports, and Apple’s docs only cover Apple platforms.
  • There is some criticism of bundling a language stdlib with the OS, but others note this is analogous to libc or the C runtime on other systems.

Security, fingerprinting, and high‑resolution timers

  • mach_absolute_time returns a high-precision monotonic value (effectively uptime/cycles since boot) and is on Apple’s “naughty list” due to fingerprinting risk.
  • Discussion explains how uptime plus wall-clock time can identify devices (especially behind NAT), and how precise timers enable micro-benchmark–based fingerprinting.
  • Some speculate the inefficiency of Swift clocks might be an intentional Spectre/Meltdown mitigation; others strongly dispute this, noting:
    • More efficient APIs (Date, clock_gettime) remain available.
    • The stack trace just shows layering/object overhead, not randomized delays.
    • Browsers mitigate timing attacks differently (fuzzing results, opt-in precision).

Performance design and async example

  • The article’s example reads time inside for try await byte in bytes, effectively timing per byte. Multiple commenters note this is intentionally contrived for benchmarking and not how production code should be structured.
  • Still, the overhead of Swift clocks seems high even compared to expected async overhead.

Alternatives, fixes, and comparisons

  • Several recommend just using clock_gettime (or the _np nanosecond variant) directly for high-performance timing.
  • Linux benchmarks are shared, showing clock_gettime via vDSO in single-digit to low tens of nanoseconds; static linking can shave off more.
  • A Swift pull request is linked, implying the core team is addressing the inefficiency.