title: Understand DispatchTime on M1 machines
body: <p>In my iOS project were were able to replicate <code>Combine's Schedulers</code> implementation and we have an extensive suit of testing, everything was fine on Intel machines all the tests were passing, now we got some of M1 machines to see if there is a showstopper in our workflow.</p>
  <p>Suddenly some of our library code starts failing, the weird thing is even if we use Combine's Implementation the tests still failing.</p>
  <p>Our assumption is we are misusing <code>DispatchTime(uptimeNanoseconds:)</code> as you can see in the following screen shot (Combine's implementation)</p>
  <p><a href="https://i.stack.imgur.com/6Zsys.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6Zsys.png" alt="enter image description here" /></a></p>
  <p>We know by now that initialising <code>DispatchTime</code> with uptimeNanoseconds value doesn't mean they are the actual nanoseconds on M1 machines, according to the docs</p>
  <blockquote>
  <p>Creates a <code>DispatchTime</code> relative to the system clock that
  ticks since boot.</p>
  </blockquote>
  <pre><code> - Parameters:
     - uptimeNanoseconds: The number of nanoseconds since boot, excluding
                          time the system spent asleep
   - Returns: A new `DispatchTime`
   - Discussion: This clock is the same as the value returned by
                 `mach_absolute_time` when converted into nanoseconds.
                 On some platforms, the nanosecond value is rounded up to a
                 multiple of the Mach timebase, using the conversion factors
                 returned by `mach_timebase_info()`. The nanosecond equivalent
                 of the rounded result can be obtained by reading the
                 `uptimeNanoseconds` property.
                 Note that `DispatchTime(uptimeNanoseconds: 0)` is
                 equivalent to `DispatchTime.now()`, that is, its value
                 represents the number of nanoseconds since boot (excluding
                 system sleep time), not zero nanoseconds since boot.
  </code></pre>
  <p>so, is the test wrong or we should not use <code>DispatchTime</code> like this?</p>
  <p>we try to follow <a href="https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code" rel="nofollow noreferrer">Apple suggestion</a> and use this:</p>
  <pre class="lang-c prettyprint-override"><code>uint64_t MachTimeToNanoseconds(uint64_t machTime)
  {
      uint64_t nanoseconds = 0;
      static mach_timebase_info_data_t sTimebase;
      if (sTimebase.denom == 0)
          (void)mach_timebase_info(&amp;sTimebase);
  
      nanoseconds = ((machTime * sTimebase.numer) / sTimebase.denom);
  
      return nanoseconds;
  }
  </code></pre>
  <p>it didnt help a lot.</p>
  <p>Edit: Screenshot code:</p>
  <pre class="lang-swift prettyprint-override"><code> func testSchedulerTimeTypeDistance() {
      let time1 = DispatchQueue.SchedulerTimeType(.init(uptimeNanoseconds: 10000))
      let time2 = DispatchQueue.SchedulerTimeType(.init(uptimeNanoseconds: 10431))
      let distantFuture = DispatchQueue.SchedulerTimeType(.distantFuture)
      let notSoDistantFuture = DispatchQueue.SchedulerTimeType(
        DispatchTime(
          uptimeNanoseconds: DispatchTime.distantFuture.uptimeNanoseconds - 1024
        )
      )
  
      XCTAssertEqual(time1.distance(to: time2), .nanoseconds(431))
      XCTAssertEqual(time2.distance(to: time1), .nanoseconds(-431))
  
      XCTAssertEqual(time1.distance(to: distantFuture), .nanoseconds(-10001))
      XCTAssertEqual(distantFuture.distance(to: time1), .nanoseconds(10001))
      XCTAssertEqual(time2.distance(to: distantFuture), .nanoseconds(-10432))
      XCTAssertEqual(distantFuture.distance(to: time2), .nanoseconds(10432))
  
      XCTAssertEqual(time1.distance(to: notSoDistantFuture), .nanoseconds(-11025))
      XCTAssertEqual(notSoDistantFuture.distance(to: time1), .nanoseconds(11025))
      XCTAssertEqual(time2.distance(to: notSoDistantFuture), .nanoseconds(-11456))
      XCTAssertEqual(notSoDistantFuture.distance(to: time2), .nanoseconds(11456))
  
      XCTAssertEqual(distantFuture.distance(to: distantFuture), .nanoseconds(0))
      XCTAssertEqual(notSoDistantFuture.distance(to: notSoDistantFuture),
                     .nanoseconds(0))
    }
  </code></pre>