Swift's native Clocks are inefficient

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.