क्या कोई समय बहुत ही सटीक तरीके से प्राप्त करने का एक आसान तरीका है?
मुझे विधि कॉल के बीच कुछ देरी की गणना करने की आवश्यकता है। विशेष रूप से, मैं एक UIScrollView में स्क्रॉलिंग की गति की गणना करना चाहता हूं।
क्या कोई समय बहुत ही सटीक तरीके से प्राप्त करने का एक आसान तरीका है?
मुझे विधि कॉल के बीच कुछ देरी की गणना करने की आवश्यकता है। विशेष रूप से, मैं एक UIScrollView में स्क्रॉलिंग की गति की गणना करना चाहता हूं।
जवाबों:
NSDate
और timeIntervalSince*
विधियाँ NSTimeInterval
उप-मिलीसेकंड सटीकता के साथ दोहरा है। NSTimeInterval
सेकंड में है, लेकिन यह आपको अधिक सटीकता प्रदान करने के लिए दोहरे का उपयोग करता है।
मिलीसेकंड समय सटीकता की गणना करने के लिए, आप कर सकते हैं:
// 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;
समय पर प्रलेखन । InvalvalSinceNow ।
इस अंतराल का उपयोग करके गणना करने के कई अन्य तरीके हैं NSDate
, और मैं कक्षा के दस्तावेज़ीकरण को देखने की सलाह दूंगाNSDate
जिसके लिए NSDate क्लास संदर्भ में पाया जाता है ।
NSDate
और mach_absolute_time()
लगभग 30ms के स्तर पर। २ बनाम २ ९, ३६ बनाम ३ ९, ४३ बनाम ४५। NSDate
मेरे लिए इस्तेमाल करना आसान था और नतीजे ध्यान न देने के समान थे।
mach_absolute_time()
सटीक माप प्राप्त करने के लिए इस्तेमाल किया जा सकता है।
Http://developer.apple.com/qa/qa2004/qa1398.html देखें
यह भी उपलब्ध है CACurrentMediaTime()
, जो अनिवार्य रूप से एक ही चीज़ है, लेकिन एक आसान-से-उपयोग इंटरफ़ेस के साथ।
(नोट: यह उत्तर 2009 में लिखा गया था। clock_gettime()
मैकले और आईओएस के नए संस्करणों में उपलब्ध सरल पॉसिक्स इंटरफेस के लिए पावेल अलेक्सीव का उत्तर देखें ।)
CACurrentMediaTime()
, जो mach_absolute_time()
सीधे एक में परिवर्तित होता है double
।
elapsedNano
प्रकार का होता है Nanoseconds
, जो एक सादे पूर्णांक प्रकार नहीं है। यह एक उपनाम है UnsignedWide
, जो दो 32-बिट पूर्णांक फ़ील्ड के साथ एक संरचना है। आप UnsignedWideToUInt64()
चाहें तो कलाकारों के बजाय उपयोग कर सकते हैं।
कृपया उपयोग न करें NSDate
, CFAbsoluteTimeGetCurrent
या gettimeofday
बीत चुके समय को मापने के लिए। ये सभी सिस्टम घड़ी पर निर्भर करते हैं, जो किसी भी समय कई अलग-अलग कारणों से बदल सकते हैं , जैसे कि नेटवर्क टाइम सिंक (NTP) घड़ी को अपडेट करना (अक्सर बहाव के लिए समायोजित करने के लिए होता है), डीएसटी समायोजन, लीप सेकंड, और इसी तरह।
इसका मतलब है कि यदि आप अपनी डाउनलोड या अपलोड गति को माप रहे हैं, तो आपको अपने नंबरों में अचानक स्पाइक्स या बूंदें मिलेंगी जो वास्तव में जो कुछ भी नहीं हुआ था, उससे संबंधित नहीं हैं; आपके प्रदर्शन परीक्षणों में अजीब गलत परिणाम होंगे; और आपकी मैनुअल टाइमर गलत अवधि के बाद ट्रिगर हो जाएगी। समय भी पीछे की ओर जा सकता है, और आप नकारात्मक डेल्टा के साथ समाप्त होते हैं, और आप अनंत पुनरावृत्ति या मृत कोड (हाँ, मैंने इन दोनों को किया है) के साथ समाप्त हो सकता है।
का उपयोग करें mach_absolute_time
। कर्नेल बूट होने के बाद से यह वास्तविक सेकंड मापता है। यह नीरस रूप से बढ़ रहा है (कभी भी पीछे नहीं हटेगा), और तारीख और समय सेटिंग से अप्रभावित है। चूंकि यह काम करने के लिए एक दर्द है, यहाँ एक सरल आवरण है जो आपको देता है NSTimeInterval
:
// 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()
क्वार्ट्जकोर से क्या ?
@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
डिवाइस रिबूट से प्रभावित हो सकता है। इसके बजाय सर्वर-टाइम का उपयोग करें।
इसके अलावा, यहां बताया गया है कि NSNumber
मिलीसेकंड में यूनिक्स युग के साथ 64-बिट की गणना कैसे की जाती है , इस मामले में कि आप इसे कोरडाटा में कैसे स्टोर करना चाहते हैं। मुझे अपने ऐप के लिए इसकी आवश्यकता थी जो एक सिस्टम के साथ इंटरैक्ट करता है जो इस तरह से स्टोर करता है।
+ (NSNumber*) longUnixEpoch {
return [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000];
}
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 के बाद से समर्थित, नींद, नीरस नहीं हैमुझे पता है कि यह एक पुराना है, लेकिन यहां तक कि मैंने खुद को फिर से अतीत में भटकते पाया, इसलिए मैंने सोचा कि मैं यहां अपना विकल्प प्रस्तुत करूंगा।
इस पर मेरे ब्लॉग पोस्ट को देखने के लिए सबसे अच्छी शर्त है: ऑब्जेक्टिव-सी में टाइमिंग चीजें: एक स्टॉपवॉच
मूल रूप से, मैंने एक वर्ग लिखा है जो बहुत ही बुनियादी तरीके से देखना बंद कर देता है, लेकिन इसे संक्षिप्त किया जाता है ताकि आपको केवल निम्नलिखित कार्य करने की आवश्यकता हो:
[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
सही समय बीतने के बजाय उपयोग करें ।
NSDate का उपयोग करके आप पहली जनवरी, 1970 से मिलीसेकंड में वर्तमान समय प्राप्त कर सकते हैं:
- (double)currentTimeInMilliseconds {
NSDate *date = [NSDate date];
return [date timeIntervalSince1970]*1000;
}
उन लोगों के लिए हमें @ जेफ थॉम्पसन के उत्तर के स्विफ्ट संस्करण की आवश्यकता है:
// 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
सही समय बीतने के बजाय ।