2

以下のコードを使用して、mach_wait_until() を使用して、指定された時間 (ナノ秒単位) 待機します。

private func startTimerAndResume(){

    let idealNanos: UInt64 = 1250130250 //1.25 seconds

    let deadline = CFAbsoluteTime(mach_absolute_time() + (timeUnitsFor(nanos: idealNanos))/100)

    let x = mach_absolute_time()

    mach_wait_until(UInt64(deadline))

    let y = mach_absolute_time()


    var timeBaseInfo = mach_timebase_info_data_t()
    mach_timebase_info(&timeBaseInfo)
    let elapsedNanos = (y - x) * UInt64(timeBaseInfo.numer) / UInt64(timeBaseInfo.denom);

    print("deadline (aka mach-abs-time + timeUnitsFor()) = \(deadline)")
    print("(mach-abs-y)-(mach-abs-x) = \(y-x)")
    print("error in time units = \((y-x)-(timeUnitsFor(nanos: idealNanos))/100)")
    print("elapsed nanos actual = ", elapsedNanos)
    print("elapsed nanos ideal = ", idealNanos)
    print("error in nanoseconds = \(elapsedNanos - idealNanos)")
}


private func timeUnitsFor(nanos: UInt64)-> UInt64{

    var timeBaseInfo = mach_timebase_info_data_t()
    mach_timebase_info(&timeBaseInfo)

    let numer: UInt64 = UInt64(timeBaseInfo.numer)
    let denom: UInt64 = UInt64(timeBaseInfo.denom)

    //elapsed time in nanoseconds = timUnits * (numer / denom) ... therefore ->
    let timeUnits: UInt64 = (nanos*denom/numer)*(UInt64(100))//multiply by 100 to preserve decimal before truncation caused by UInt64() conversion
    print("timeUnits = \((timeUnits)/100) for target nanos \(nanos) when numer = \(numer) and denom = \(denom)")
    return timeUnits
}

実際の iPhone デバイスでこれを実行すると、エラーは通常約 1 ミリ秒で、出力は次のようになります。

timeUnits = 30003126 for target nanos 1250130250 when numer = 125 and denom = 3

deadline (aka mach-abs-time + timeUnitsFor()) = 4025277628801.0

(mach-abs-y)-(mach-abs-x) = 30027213

timeUnits = 30003126 for target nanos 1250130250 when numer = 125 and denom = 3

error in time units = 24087

elapsed nanos actual = 1251133875

elapsed nanos ideal = 1250130250

error in nanoseconds = 1003625

ただし、シミュレーターでこれを実行すると、タイマーは一貫して 70 ~ 74 ミリ秒遅れます。出力は次のとおりです。

timeUnits = 1250130250 for target nanos 1250130250 when numer = 1 and denom = 1

deadline (aka mach-abs-time + timeUnitsFor()) = 691695760744956.0

(mach-abs-y)-(mach-abs-x) = 1322288698

timeUnits = 1250130250 for target nanos 1250130250 when numer = 1 and denom = 1

error in time units = 72158448

elapsed nanos actual = 1322288698

elapsed nanos ideal = 1250130250

error in nanoseconds = 72158448

シミュレーターが毎回 70 ~ 74 ミリ秒遅れている理由を知りたいです。ナノ秒単位とマッハ時間単位の間の変換を間違っていますか? ありがとう

4

1 に答える 1

1

シミュレータは、クロックサイクルに正確なテスト用のクロックサイクルに正確なアーム エミュレータではありません。これは Intel 用の iOS のビルドであり、カーネルをホスト OS の残りの部分と共有します。

タイマーがデバイス上になくても、シミュレーターで合体している可能性があります。ホスト構成とランタイム バージョンによっては、シミュレーター プロセスがユーティリティ QoS 層で実行されている場合があります。

したがって、タイミングに違いが見られる理由は、次の 1 つ以上の理由によるものです。

  • インテル vs ARM
  • 異なるカーネル バージョン (ホスト カーネルとペアの iOS カーネル バージョン)
  • システム上の他のプロセスとの競合
  • 異なる QoS 層によるタイマー結合

特定のウィンドウ内で制御を取り戻すことに依存するべきではありません。これは API コントラクトに含まれていないからです。その時間が経過した後、ある時点でスケジュールされます。

于 2016-11-29T17:43:33.887 に答える