web-dev-qa-db-ja.com

たとえば、Objective-Cでミリ秒単位の正確な時間を取得するにはどうすればよいですか?

非常に正確に時間を取得する簡単な方法はありますか?

メソッド呼び出し間の遅延を計算する必要があります。具体的には、UIScrollViewでのスクロール速度を計算します。

97
Thanks

mach_absolute_time()を使用して、正確な測定値を取得できます。

http://developer.Apple.com/qa/qa2004/qa1398.html を参照してください

CACurrentMediaTime()も利用できます。これは基本的に同じものですが、使いやすいインターフェースを備えています。

40

経過時間の測定にNSDateCFAbsoluteTimeGetCurrent、またはgettimeofdayを使用しないでください。これらはすべてシステムクロックに依存します。システムクロックは、ネットワーク時刻同期(NTP)がクロックを更新する(ドリフトを調整することが多い)、DST調整など、さまざまな理由によりany時間で変更される可能性があります。うるう秒など。

これは、ダウンロードまたはアップロードの速度を測定している場合、実際の出来事とは関係のない突然の急増または急落が発生することを意味します。パフォーマンステストには、奇妙で不正確な外れ値が含まれます。手動タイマーは、不適切な期間の後にトリガーされます。時間は逆戻りすることさえあり、負のデルタになり、無限再帰またはデッドコードになります(はい、私はこれらの両方を行いました)。

つかいます mach_absolute_time。カーネルがブートされてからの実際の秒数を測定します。単調に増加し(逆戻りすることはありません)、日付と時刻の設定の影響を受けません。苦労するので、NSTimeIntervalsを提供する簡単なラッパーを次に示します。

// LBClock.h
@interface LBClock : NSObject
+ (instancetype)sharedClock;
// since device boot or something. Monotonically increasing, unaffected by date and time settings
- (NSTimeInterval)absoluteTime;

- (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute;
@end

// LBClock.m
#include <mach/mach.h>
#include <mach/mach_time.h>

@implementation LBClock
{
    mach_timebase_info_data_t _clock_timebase;
}

+ (instancetype)sharedClock
{
    static LBClock *g;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        g = [LBClock new];
    });
    return g;
}

- (id)init
{
    if(!(self = [super init]))
        return nil;
    mach_timebase_info(&_clock_timebase);
    return self;
}

- (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute
{
    uint64_t nanos = (machAbsolute * _clock_timebase.numer) / _clock_timebase.denom;

    return nanos/1.0e9;
}

- (NSTimeInterval)absoluteTime
{
    uint64_t machtime = mach_absolute_time();
    return [self machAbsoluteToTimeInterval:machtime];
}
@end
26
nevyn

CFAbsoluteTimeGetCurrent() は絶対時間をdouble値として返しますが、その精度がわからない-it mightは数十ミリ秒ごとに更新するだけです。または、マイクロ秒ごとに更新するかもしれません。

14
Adam Rosenfield

mach_absolute_time()は使用しません。これは、ティックを使用して絶対時間(おそらくアップタイム)でカーネルとプロセッサの組み合わせを照会するためです。

私が使用するもの:

_CFAbsoluteTimeGetCurrent();
_

この機能は、iOSとOSXのソフトウェアとハ​​ードウェアの違いを修正するために最適化されています。

Something Geekier

mach_absolute_time()AFAbsoluteTimeGetCurrent()の差の商は常に約24000011.154871です。

ここに私のアプリのログがあります:

最終結果時間はCFAbsoluteTimeGetCurrent() 'sの違いであることに注意してください

_ 2012-03-19 21:46:35.609 Rest Counter[3776:707] First Time: 353900795.609040
 2012-03-19 21:46:36.360 Rest Counter[3776:707] Second Time: 353900796.360177
 2012-03-19 21:46:36.361 Rest Counter[3776:707] Final Result Time (difference): 0.751137
 2012-03-19 21:46:36.363 Rest Counter[3776:707] Mach absolute time: 18027372
 2012-03-19 21:46:36.365 Rest Counter[3776:707] Mach absolute time/final time: 24000113.153295
 2012-03-19 21:46:36.367 Rest Counter[3776:707] -----------------------------------------------------
 2012-03-19 21:46:43.074 Rest Counter[3776:707] First Time: 353900803.074637
 2012-03-19 21:46:43.170 Rest Counter[3776:707] Second Time: 353900803.170256
 2012-03-19 21:46:43.172 Rest Counter[3776:707] Final Result Time (difference): 0.095619
 2012-03-19 21:46:43.173 Rest Counter[3776:707] Mach absolute time: 2294833
 2012-03-19 21:46:43.175 Rest Counter[3776:707] Mach absolute time/final time: 23999753.727777
 2012-03-19 21:46:43.177 Rest Counter[3776:707] -----------------------------------------------------
 2012-03-19 21:46:46.499 Rest Counter[3776:707] First Time: 353900806.499199
 2012-03-19 21:46:55.017 Rest Counter[3776:707] Second Time: 353900815.016985
 2012-03-19 21:46:55.018 Rest Counter[3776:707] Final Result Time (difference): 8.517786
 2012-03-19 21:46:55.020 Rest Counter[3776:707] Mach absolute time: 204426836
 2012-03-19 21:46:55.022 Rest Counter[3776:707] Mach absolute time/final time: 23999996.639500
 2012-03-19 21:46:55.024 Rest Counter[3776:707] -----------------------------------------------------
_
10
Nate Symer
#define CTTimeStart() NSDate * __date = [NSDate date]
#define CTTimeEnd(MSG) NSLog(MSG " %g",[__date timeIntervalSinceNow]*-1)

使用法:

CTTimeStart();
...
CTTimeEnd(@"that was a long time:");

出力:

2013-08-23 15:34:39.558 App-Dev[21229:907] that was a long time: .0023
6
gngrwzrd

また、Unixエポックで初期化された64ビットNSNumberをミリ秒単位で計算する方法もここにあります。それがCoreDataでの格納方法です。この方法で日付を保存するシステムとやり取りするアプリにこれが必要でした。

  + (NSNumber*) longUnixEpoch {
      return [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000];
  }
4
John Wright

_mach_absolute_time_に基づく関数は、短い測定に適しています。
ただし、長時間の測定では、デバイスがスリープしている間はカチカチ音がしないという重要な注意事項があります。

起動後の時間を取得する機能があります。寝ている間も止まりません。また、gettimeofdayは単調ではありませんが、私の実験では、システム時間が変わるとブート時間が変わることが常にあるので、うまく動作するはずです。

_func timeSinceBoot() -> TimeInterval
{
    var bootTime = timeval()
    var currentTime = timeval()
    var timeZone = timezone()

    let mib = UnsafeMutablePointer<Int32>.allocate(capacity: 2)
    mib[0] = CTL_KERN
    mib[1] = KERN_BOOTTIME
    var size = MemoryLayout.size(ofValue: bootTime)

    var timeSinceBoot = 0.0

    gettimeofday(&currentTime, &timeZone)

    if sysctl(mib, 2, &bootTime, &size, nil, 0) != -1 && bootTime.tv_sec != 0 {
        timeSinceBoot = Double(currentTime.tv_sec - bootTime.tv_sec)
        timeSinceBoot += Double(currentTime.tv_usec - bootTime.tv_usec) / 1000000.0
    }
    return timeSinceBoot
}
_

また、iOS 10およびmacOS 10.12以降では、CLOCK_MONOTONICを使用できます。

_if #available(OSX 10.12, *) {
    var uptime = timespec()
    if clock_gettime(CLOCK_MONOTONIC_RAW, &uptime) == 0 {
        return Double(uptime.tv_sec) + Double(uptime.tv_nsec) / 1000000000.0
    }
}
_

まとめると:

  • _Date.timeIntervalSinceReferenceDate_ —単調ではなく、システム時間の変更時に変更
  • CFAbsoluteTimeGetCurrent() —単調ではなく、後方に進む可能性があります
  • CACurrentMediaTime() —デバイスがスリープ状態になるとカチカチ音をたてなくなります
  • timeSinceBoot() —スリープしませんが、単調ではない場合があります
  • _CLOCK_MONOTONIC_ —スリープせず、単調で、iOS 10以降でサポートされています
2
Pavel Alexeev

NSDateを使用すると、1970年1月1日から現在の時刻をミリ秒単位で取得できます。

- (double)currentTimeInMilliseconds {
    NSDate *date = [NSDate date];
    return [date timeIntervalSince1970]*1000;
}
1
Camilo Ortegón

私はこれが古いものであることを知っていますが、私はそれをもう一度通り過ぎてさまよいました。

最善の策は、これに関する私のブログ投稿をチェックすることです: Objective-Cのタイミング:ストップウォッチ

基本的に、非常に基本的な方法で視聴を停止するクラスを作成しましたが、カプセル化されているため、次の操作を行うだけで済みます。

[MMStopwatchARC start:@"My Timer"];
// your work here ...
[MMStopwatchARC stop:@"My Timer"];

そして、次のようになります。

MyApp[4090:15203]  -> Stopwatch: [My Timer] runtime: [0.029]

ログに...

もう一度、もう少し私の投稿をチェックするか、ここからダウンロードしてください: MMStopwatch.Zip

1
bladnman