時間を正確に取得する簡単な方法はありますか?
メソッド呼び出し間の遅延を計算する必要があります。具体的には、UIScrollViewでのスクロール速度を計算したいと思います。
時間を正確に取得する簡単な方法はありますか?
メソッド呼び出し間の遅延を計算する必要があります。具体的には、UIScrollViewでのスクロール速度を計算したいと思います。
回答:
NSDate
そして、timeIntervalSince*
メソッドはNSTimeInterval
サブミリ秒の精度でdoubleであるa を返します。NSTimeInterval
秒単位ですが、精度を上げるためにdoubleを使用しています。
ミリ秒の時間精度を計算するには、次のようにします。
// Get a current time for where you want to start measuring from
NSDate *date = [NSDate date];
// do work...
// Find elapsed time and convert to milliseconds
// Use (-) modifier to conversion since receiver is earlier than now
double timePassed_ms = [date timeIntervalSinceNow] * -1000.0;
timeIntervalSinceNowに関するドキュメント。
そこ使用して、この間隔を計算するための他の多くの方法がありますがNSDate
、私はのためのクラスのドキュメントを見て推薦NSDate
で発見されました。NSDateクラスリファレンスに参照ます。
NSDate
しmach_absolute_time()
ました。27対29、36対39、43対45 NSDate
は私にとって使いやすく、結果は気にしないほど十分に似ていました。
mach_absolute_time()
正確な測定値を取得するために使用できます。
http://developer.apple.com/qa/qa2004/qa1398.htmlを参照してください
も利用できますCACurrentMediaTime()
。これは基本的に同じものですが、使いやすいインターフェースを備えています。
(注:この回答は2009年に書かれたものです。clock_gettime()
新しいバージョンのmacOSおよびiOSで利用できるより単純なPOSIX インターフェイスについては、Pavel Alexeevの回答を参照してください。)
CACurrentMediaTime()
変換mach_absolute_time()
する便利なメソッドも提供しますdouble
。
elapsedNano
はタイプNanoseconds
であり、単純な整数タイプではありません。これUnsignedWide
は、2つの32ビット整数フィールドを持つ構造体であるのエイリアスです。UnsignedWideToUInt64()
キャストの代わりに使用することもできます。
使用しないでくださいNSDate
、CFAbsoluteTimeGetCurrent
またはgettimeofday
経過時間を計測します。これらはすべてシステムクロックに依存します。システムクロックは、ネットワークタイム同期(NTP)によるクロックの更新(頻繁にドリフトの調整が行われる)、DST調整、うるう秒など、さまざまな理由によりいつでも変更できます。
これは、ダウンロードまたはアップロードの速度を測定している場合、実際に何が起こったかとは関係のない、急激な数値の急上昇または低下が生じることを意味します。パフォーマンステストには、奇妙な不正確な外れ値が含まれます。手動タイマーは、不適切な期間の後にトリガーされます。時間は逆戻りする可能性があり、最終的に負のデルタが発生し、無限再帰またはデッドコードが発生する可能性があります(そうです、私はこれらの両方を実行しました)。
を使用しmach_absolute_time
ます。カーネルがブートされてからの実際の秒数を測定します。単調に増加し(後戻りすることはありません)、日付と時刻の設定の影響を受けません。作業が面倒なので、ここにNSTimeInterval
s を提供する単純なラッパーを示します。
// 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
CACurrentMediaTime()
QuartzCoreから?
@import Darwin;
代わりに#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
リターンとして絶対時間double
値を、私はその精度があるかわからない-それは可能性があるだけで、すべての十ミリ秒を更新するか、それがすべてのマイクロ秒を更新する可能性があります、私は知りません。
72.89674947369
他のすべての値を考慮すると、秒の値はかなり珍しいと言わざるを得ません。;)
mach_absolute_time()
ティックを使用して絶対時間(おそらく稼働時間)をカーネルとプロセッサの組み合わせに問い合わせるため、私は使用しません。
私が使うもの:
CFAbsoluteTimeGetCurrent();
この機能は、iOSとOSXのソフトウェアとハードウェアの違いを修正するために最適化されています。
なんかゲキエ
違いの商mach_absolute_time()
とは、AFAbsoluteTimeGetCurrent()
常に周り24000011.154871です
これが私のアプリのログです:
最終結果の時間がの差であることをしてくださいノートCFAbsoluteTimeGetCurrent()
さん
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] -----------------------------------------------------
mach_absolute_time()
することにmach_timebase_info_data
なり、その後使用しました(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
。マッハタイムベースを取得するには、行うことができます(void)mach_timebase_info(&your_timebase);
#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
NSDate
いつでも変更できるシステムクロックに依存し、誤った時間間隔または負の時間間隔になる可能性があります。mach_absolute_time
代わりに、正しい経過時間を取得するために使用してください。
mach_absolute_time
デバイスの再起動によって影響を受ける可能性があります。代わりにサーバー時間を使用してください。
に基づく関数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(¤tTime, &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以降でサポートこれは古いものであることは知っていますが、自分が再びそれを通り過ぎていることに気付いたので、ここに自分のオプションを提出したいと思いました。
最善の策は、これに関する私のブログ投稿をチェックすることです: Objective-Cでのタイミングのタイミング:ストップウォッチ
基本的に、私は非常に基本的な方法で監視を停止するクラスを作成しましたが、カプセル化されているため、次のことだけを実行する必要があります。
[MMStopwatchARC start:@"My Timer"];
// your work here ...
[MMStopwatchARC stop:@"My Timer"];
そしてあなたは次のようになります:
MyApp[4090:15203] -> Stopwatch: [My Timer] runtime: [0.029]
ログに...
もう一度、もう少し私の投稿をチェックするか、ここからダウンロードしてください: MMStopwatch.zip
NSDate
いつでも変更できるシステムクロックに依存し、誤った時間間隔または負の時間間隔になる可能性があります。mach_absolute_time
代わりに、正しい経過時間を取得するために使用してください。
それらには、@ Jeff Thompsonの回答のSwiftバージョンが必要です。
// Get a current time for where you want to start measuring from
var date = NSDate()
// do work...
// Find elapsed time and convert to milliseconds
// Use (-) modifier to conversion since receiver is earlier than now
var timePassed_ms: Double = date.timeIntervalSinceNow * -1000.0
これがお役に立てば幸いです。
NSDate
いつでも変更できるシステムクロックに依存し、誤った時間間隔または負の時間間隔になる可能性があります。mach_absolute_time
代わりに、正しい経過時間を取得するために使用してください。