क्या यह निर्धारित करने का एक तरीका है कि विधि (मिलीसेकंड में) निष्पादित करने के लिए कितना समय चाहिए?
क्या यह निर्धारित करने का एक तरीका है कि विधि (मिलीसेकंड में) निष्पादित करने के लिए कितना समय चाहिए?
जवाबों:
NSDate *methodStart = [NSDate date];
/* ... Do whatever you need to do ... */
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
स्विफ्ट:
let methodStart = NSDate()
/* ... Do whatever you need to do ... */
let methodFinish = NSDate()
let executionTime = methodFinish.timeIntervalSinceDate(methodStart)
print("Execution time: \(executionTime)")
Swift3:
let methodStart = Date()
/* ... Do whatever you need to do ... */
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
उपयोग में आसान और उप-मिलीसेकंड सटीक है।
NSLog(@"executionTime = %f", executionTime);
NSDate
और mach_absolute_time()
लगभग 30ms के स्तर पर। 27 बनाम 29, 36 बनाम 39, 43 बनाम 45. NSDate
मेरे लिए उपयोग करना आसान था और परिणाम समान थे कि परेशान न करें mach_absolute_time()
।
यहां दो एक-लाइन मैक्रो हैं, जिनका मैं उपयोग करता हूं:
#define TICK NSDate *startTime = [NSDate date]
#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])
इसे इस तरह उपयोग करें:
TICK;
/* ... Do Some Work Here ... */
TOCK;
#define TOCK NSLog(@"%s Time: %f", __func__, -[startTime timeIntervalSinceNow])
यह जवाब देता है कि टाइमर किस फ़ंक्शन में उपयोग किया गया था। यदि मैंने कई कार्यों के लिए टिक TOCK का उपयोग किया तो मुझे यह उपयोगी लगा।
__PRETTY_FUNCTION__
और __LINE__
यदि आप अधिक विस्तृत जानकारी चाहते हैं।
OS X पर ठीक-ठाक समय के लिए, आपको निम्न mach_absolute_time( )
में घोषित का उपयोग करना चाहिए <mach/mach_time.h>
:
#include <mach/mach_time.h>
#include <stdint.h>
// Do some stuff to setup for timing
const uint64_t startTime = mach_absolute_time();
// Do some stuff that you want to time
const uint64_t endTime = mach_absolute_time();
// Time elapsed in Mach time units.
const uint64_t elapsedMTU = endTime - startTime;
// Get information for converting from MTU to nanoseconds
mach_timebase_info_data_t info;
if (mach_timebase_info(&info))
handleErrorConditionIfYoureBeingCareful();
// Get elapsed time in nanoseconds:
const double elapsedNS = (double)elapsedMTU * (double)info.numer / (double)info.denom;
निश्चित रूप से ठीक-ठीक माप के बारे में सामान्य कैविट्स लागू होते हैं; आप शायद कई बार परीक्षण के तहत दिनचर्या को लागू करने के लिए सबसे अच्छा कर रहे हैं, और औसत / न्यूनतम / कुछ अन्य प्रसंस्करण के रूप में ले रहे हैं।
साथ ही, कृपया ध्यान दें कि आप इसे और अधिक उपयोगी करने के लिए लग सकता है कि प्रोफ़ाइल आपके आवेदन शार्क की तरह एक उपकरण का उपयोग कर चल रहा है। यह आपको सटीक समय की जानकारी नहीं देगा, लेकिन यह आपको बताएगा कि आवेदन के समय का कितना प्रतिशत कहाँ खर्च किया जा रहा है, जो अक्सर अधिक उपयोगी होता है (लेकिन हमेशा नहीं)।
इसके लिए एक सुविधाजनक आवरण है mach_absolute_time()
- यह एक CACurrentMediaTime()
फ़ंक्शन है।
इसके विपरीत
NSDate
याCFAbsoluteTimeGetCurrent()
ऑफसेट,mach_absolute_time()
औरCACurrentMediaTime()
आंतरिक होस्ट घड़ी पर आधारित होते हैं, एक सटीक, एकराट माप, और बाहरी समय संदर्भ में परिवर्तन के अधीन नहीं होते हैं, जैसे कि समय क्षेत्र, दिन की बचत, या छलांग सेकंड के कारण।
ObjC
CFTimeInterval startTime = CACurrentMediaTime();
// Do your stuff here
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(@"Total Runtime: %g s", endTime - startTime);
तीव्र
let startTime = CACurrentMediaTime()
// Do your stuff here
let endTime = CACurrentMediaTime()
print("Total Runtime: \(endTime - startTime) s")
NSDate
।
स्विफ्ट में, मैं उपयोग कर रहा हूं:
मेरे मैक्रों.स्विफ्ट में मैंने अभी-अभी जोड़ा है
var startTime = NSDate()
func TICK(){ startTime = NSDate() }
func TOCK(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__){
println("\(function) Time: \(startTime.timeIntervalSinceNow)\nLine:\(line) File: \(file)")
}
अब आप कहीं भी कॉल कर सकते हैं
TICK()
// your code to be tracked
TOCK()
\(-startTime.timeIntervalSinceNow)
(नकारात्मक को नोटिस करें)
मुझे पता है कि यह एक पुराना है, लेकिन यहां तक कि मैंने खुद को फिर से अतीत में भटकते पाया, इसलिए मैंने सोचा कि मैं यहां अपना विकल्प प्रस्तुत करूंगा।
इस पर मेरे ब्लॉग पोस्ट को देखने के लिए सबसे अच्छी शर्त है: ऑब्जेक्टिव-सी में टाइमिंग चीजें: एक स्टॉपवॉच
मूल रूप से, मैंने एक वर्ग लिखा है जो बहुत ही मूल तरीके से देखना बंद कर देता है, लेकिन इसे संक्षिप्त किया जाता है ताकि आपको केवल निम्नलिखित कार्य करने की आवश्यकता हो:
[MMStopwatchARC start:@"My Timer"];
// your work here ...
[MMStopwatchARC stop:@"My Timer"];
और आप के साथ अंत:
MyApp[4090:15203] -> Stopwatch: [My Timer] runtime: [0.029]
लॉग में ...
फिर से, मेरी पोस्ट को थोड़ा और देखें या इसे यहाँ डाउनलोड करें: MMStopwatch.zip
मैं रॉन के समाधान के आधार पर मैक्रोज़ का उपयोग करता हूं ।
#define TICK(XXX) NSDate *XXX = [NSDate date]
#define TOCK(XXX) NSLog(@"%s: %f", #XXX, -[XXX timeIntervalSinceNow])
कोड की पंक्तियों के लिए:
TICK(TIME1);
/// do job here
TOCK(TIME1);
हम कंसोल में कुछ इस तरह देखेंगे: TIME1: 0.096618
मैं इस ब्लॉग पोस्ट के कोड से प्रेरित एक न्यूनतम, एक पेज क्लास कार्यान्वयन का उपयोग करता हूं :
#import <mach/mach_time.h>
@interface DBGStopwatch : NSObject
+ (void)start:(NSString *)name;
+ (void)stop:(NSString *)name;
@end
@implementation DBGStopwatch
+ (NSMutableDictionary *)watches {
static NSMutableDictionary *Watches = nil;
static dispatch_once_t OnceToken;
dispatch_once(&OnceToken, ^{
Watches = @{}.mutableCopy;
});
return Watches;
}
+ (double)secondsFromMachTime:(uint64_t)time {
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
return (double)time * (double)timebase.numer /
(double)timebase.denom / 1e9;
}
+ (void)start:(NSString *)name {
uint64_t begin = mach_absolute_time();
self.watches[name] = @(begin);
}
+ (void)stop:(NSString *)name {
uint64_t end = mach_absolute_time();
uint64_t begin = [self.watches[name] unsignedLongLongValue];
DDLogInfo(@"Time taken for %@ %g s",
name, [self secondsFromMachTime:(end - begin)]);
[self.watches removeObjectForKey:name];
}
@end
इसका उपयोग बहुत सरल है:
[DBGStopwatch start:@"slow-operation"];
शुरुआत में[DBGStopwatch stop:@"slow-operation"];
खत्म होने के बाद, समय पाने के लिएआप इस स्टॉपवॉच क्लास का उपयोग करके वास्तव में ठीक समय (सेकंड के सेकंड) पा सकते हैं । यह iPhone में उच्च परिशुद्धता टाइमर का उपयोग करता है। NSDate का उपयोग करने से आपको केवल दूसरी (एस) सटीकता प्राप्त होगी। यह संस्करण विशेष रूप से ऑटोरेलिज़ और ऑब्जेक्टिव-सी के लिए डिज़ाइन किया गया है। यदि आवश्यक हो तो मेरे पास एक c ++ संस्करण है। आप यहाँ c ++ संस्करण पा सकते हैं ।
StopWatch.h
#import <Foundation/Foundation.h>
@interface StopWatch : NSObject
{
uint64_t _start;
uint64_t _stop;
uint64_t _elapsed;
}
-(void) Start;
-(void) Stop;
-(void) StopWithContext:(NSString*) context;
-(double) seconds;
-(NSString*) description;
+(StopWatch*) stopWatch;
-(StopWatch*) init;
@end
StopWatch.m
#import "StopWatch.h"
#include <mach/mach_time.h>
@implementation StopWatch
-(void) Start
{
_stop = 0;
_elapsed = 0;
_start = mach_absolute_time();
}
-(void) Stop
{
_stop = mach_absolute_time();
if(_stop > _start)
{
_elapsed = _stop - _start;
}
else
{
_elapsed = 0;
}
_start = mach_absolute_time();
}
-(void) StopWithContext:(NSString*) context
{
_stop = mach_absolute_time();
if(_stop > _start)
{
_elapsed = _stop - _start;
}
else
{
_elapsed = 0;
}
NSLog([NSString stringWithFormat:@"[%@] Stopped at %f",context,[self seconds]]);
_start = mach_absolute_time();
}
-(double) seconds
{
if(_elapsed > 0)
{
uint64_t elapsedTimeNano = 0;
mach_timebase_info_data_t timeBaseInfo;
mach_timebase_info(&timeBaseInfo);
elapsedTimeNano = _elapsed * timeBaseInfo.numer / timeBaseInfo.denom;
double elapsedSeconds = elapsedTimeNano * 1.0E-9;
return elapsedSeconds;
}
return 0.0;
}
-(NSString*) description
{
return [NSString stringWithFormat:@"%f secs.",[self seconds]];
}
+(StopWatch*) stopWatch
{
StopWatch* obj = [[[StopWatch alloc] init] autorelease];
return obj;
}
-(StopWatch*) init
{
[super init];
return self;
}
@end
कक्षा में एक स्थैतिक stopWatch
विधि होती है जो ऑटोरेल्ड ऑब्जेक्ट लौटाती है।
एक बार कॉल करने के बाद, बीता हुआ समय पाने के start
लिए seconds
विधि का उपयोग करें । start
इसे पुनः आरंभ करने के लिए फिर से कॉल करें। या stop
इसे रोकना है। आप कॉल करने के seconds
बाद भी कभी भी समय (कॉल ) पढ़ सकते हैं stop
।
एक कार्य में उदाहरण (निष्पादन की समयबद्धता)
-(void)SomeFunc
{
StopWatch* stopWatch = [StopWatch stopWatch];
[stopWatch Start];
... do stuff
[stopWatch StopWithContext:[NSString stringWithFormat:@"Created %d Records",[records count]]];
}
मैं इस कोड का उपयोग करता हूं:
#import <mach/mach_time.h>
float TIME_BLOCK(NSString *key, void (^block)(void)) {
mach_timebase_info_data_t info;
if (mach_timebase_info(&info) != KERN_SUCCESS)
{
return -1.0;
}
uint64_t start = mach_absolute_time();
block();
uint64_t end = mach_absolute_time();
uint64_t elapsed = end - start;
uint64_t nanos = elapsed * info.numer / info.denom;
float cost = (float)nanos / NSEC_PER_SEC;
NSLog(@"key: %@ (%f ms)\n", key, cost * 1000);
return cost;
}
मैं इसका उपयोग करता हूं:
clock_t start, end;
double elapsed;
start = clock();
//Start code to time
//End code to time
end = clock();
elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
NSLog(@"Time: %f",elapsed);
लेकिन मैं iPhone पर CLOCKS_PER_SEC के बारे में निश्चित नहीं हूं। आप इसे छोड़ना चाह सकते हैं।
mach_absolute_time()
स्विफ्ट 4 में उपयोग करके बारीक-बारीक समय का एक उदाहरण :
let start = mach_absolute_time()
// do something
let elapsedMTU = mach_absolute_time() - start
var timebase = mach_timebase_info()
if mach_timebase_info(&timebase) == 0 {
let elapsed = Double(elapsedMTU) * Double(timebase.numer) / Double(timebase.denom)
print("render took \(elapsed)")
}
else {
print("timebase error")
}
ठीक है, अगर आपका उद्देश्य यह पता लगाना है कि आप इसे और तेज़ बनाने के लिए क्या तय कर सकते हैं, तो यह थोड़ा अलग लक्ष्य है। उस समय को मापना जो कार्य करता है, यह पता लगाने का एक अच्छा तरीका है कि आपने क्या अंतर किया है, लेकिन यह पता लगाने के लिए कि आपको एक अलग तकनीक की आवश्यकता क्या है । यह वही है जो मैं सुझाता हूं , और मुझे पता है कि आप इसे आईफ़ोन पर कर सकते हैं।
संपादित करें: समीक्षकों ने सुझाव दिया कि मैं उत्तर को विस्तृत करता हूं, इसलिए मैं इसे कहने के लिए एक संक्षिप्त तरीका सोचने की कोशिश कर रहा हूं।
आपका समग्र कार्यक्रम आपको परेशान करने के लिए पर्याप्त समय लेता है। मान लीजिए कि N सेकंड है।
आप मान रहे हैं कि आप इसे गति दे सकते हैं। केवल एक ही तरीका है कि आप यह कर सकते हैं कि यह उस समय में कुछ नहीं कर रहा है, मी सेकंड के लिए लेखांकन ।
आप शुरू में नहीं जानते कि वह चीज क्या है। आप अनुमान लगा सकते हैं, जैसा कि सभी प्रोग्रामर करते हैं, लेकिन यह आसानी से कुछ और हो सकता है। जो भी है, यहाँ है कि आप इसे कैसे पा सकते हैं:
उस चीज़ के बाद से, जो कुछ भी है, उस समय के अंश m / N के लिए खाता है, इसका मतलब है कि यदि आप इसे यादृच्छिक रूप से रोकते हैं तो संभावना m / N है कि आप इसे उस चीज़ को करने के कार्य में पकड़ लेंगे। बेशक यह कुछ और कर रहा हो, लेकिन इसे रोकें और देखें कि यह क्या कर रहा है।
अब फिर से करो। यदि आप इसे फिर से वही काम करते हुए देखते हैं, तो आप अधिक संदिग्ध हो सकते हैं।
इसे 10 बार करें, या 20. अब यदि आप इसे किसी विशेष चीज़ (चाहे आप इसका वर्णन कैसे करें) को कई ठहरावों पर करते हुए देखते हैं, जिससे आप छुटकारा पा सकते हैं, तो आप दो बातें जानते हैं। आप बहुत हद तक जानते हैं कि समय कितना अंश लेता है, लेकिन आप ठीक-ठीक जानते हैं कि क्या ठीक करना है।
अगर आप भी जानना चाहते हैं कि वास्तव में कितना समय बचेगा, तो यह आसान है। पहले इसे मापें, इसे ठीक करें और इसके बाद इसे मापें। यदि आप वास्तव में निराश हैं, तो ठीक करें।
क्या आप देखते हैं कि यह मापने से कैसे अलग है? यह खोज रहा है, माप नहीं रहा है । अधिकांश रूपरेखा को यथासंभव यथासंभव मापने पर आधारित है, जैसे कि यह महत्वपूर्ण है, और हाथ-लहरों को पहचानने की समस्या को ठीक करने की आवश्यकता है। प्रोफाइलिंग से हर समस्या का पता नहीं चलता है, लेकिन इस पद्धति से हर समस्या का पता चलता है, और यह समस्याएँ हैं जो आपको नहीं लगती हैं जो आपको चोट पहुँचाती हैं।
यहां एक और तरीका है, स्विफ्ट में, डेफर कीवर्ड का उपयोग करने का
func methodName() {
let methodStart = Date()
defer {
let executionTime = Date().timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
}
// do your stuff here
}
Apple के डॉक्स से : डिफर स्टेटमेंट उस दायरे से बाहर प्रोग्राम कंट्रोल ट्रांसफर करने से ठीक पहले कोड को निष्पादित करने के लिए उपयोग किया जाता है, जिसमें डीफर स्टेटमेंट दिखाई देता है।
यह संबंधित कोड समूहीकृत होने के लाभ के साथ एक कोशिश / अंत में ब्लॉक के समान है।
मैं अपने बर्तनों के पुस्तकालय में इसका उपयोग करता हूं ( स्विफ्ट 4.2 ):
public class PrintTimer {
let start = Date()
let name: String
public init(file: String=#file, line: Int=#line, function: String=#function, name: String?=nil) {
let file = file.split(separator: "/").last!
self.name = name ?? "\(file):\(line) - \(function)"
}
public func done() {
let end = Date()
print("\(self.name) took \((end.timeIntervalSinceReferenceDate - self.start.timeIntervalSinceReferenceDate).roundToSigFigs(5)) s.")
}
}
... फिर एक विधि में कॉल करें जैसे:
func myFunctionCall() {
let timer = PrintTimer()
// ...
timer.done()
}
... जो चलने के बाद कंसोल में इस तरह दिखता है:
MyFile.swift:225 - myFunctionCall() took 1.8623 s.
ऊपर दिए गए टिक / टीओसीके के अनुसार संक्षिप्त नहीं है, लेकिन यह देखने के लिए पर्याप्त है कि यह क्या कर रहा है और स्वचालित रूप से इसमें शामिल है कि क्या समयबद्ध हो रहा है (फ़ाइल द्वारा, विधि की शुरुआत में लाइन, और फ़ंक्शन नाम)। जाहिर है अगर मैं और अधिक विवरण चाहता था (पूर्व, अगर मैं केवल एक विधि कॉल नहीं कर रहा हूं जैसा कि सामान्य मामला है, बल्कि उस पद्धति के भीतर एक ब्लॉक का समय निर्धारित कर रहा हूं) मैं PrintTimer init पर "name =" Foo "" पैरामीटर जोड़ सकता हूं यह चूक के अलावा कुछ नाम रखने के लिए।
चूंकि आप UIWebView में एक पेज से दूसरे पेज पर जाने के लिए समय का अनुकूलन करना चाहते हैं, तो क्या इसका मतलब यह नहीं है कि आप वास्तव में इन पृष्ठों को लोड करने में उपयोग किए जाने वाले जावास्क्रिप्ट का अनुकूलन करना चाहते हैं?
उस अंत तक, मैं एक WebKit प्रोफाइलर को देखूंगा जैसे कि यहां बात की गई है:
http://www.alertdebugging.com/2009/04/29/building-a-better-javascript-profiler-with-webkit/
एक और दृष्टिकोण उच्च स्तर पर शुरू होगा, और यह सोचें कि आप हर बार पूरे वेबव्यू को रीफ्रेश करने के बजाय AJAX स्टाइल पेज लोडिंग का उपयोग करके लोड के समय को कम करने के लिए प्रश्न में वेब पेज कैसे डिज़ाइन कर सकते हैं।
struct TIME {
static var ti = mach_timebase_info()
static var k: Double = 1
static var mach_stamp: Double {
if ti.denom == 0 {
mach_timebase_info(&ti)
k = Double(ti.numer) / Double(ti.denom) * 1e-6
}
return Double(mach_absolute_time()) * k
}
static var stamp: Double { return NSDate.timeIntervalSinceReferenceDate() * 1000 }
}
do {
let mach_start = TIME.mach_stamp
usleep(200000)
let mach_diff = TIME.mach_stamp - mach_start
let start = TIME.stamp
usleep(200000)
let diff = TIME.stamp - start
print(mach_diff, diff)
}
यहां लंबी प्रक्रिया चलाने के लिए कहीं भी कोडिंग करने के लिए स्विफ्ट 3 समाधान है।
var increment: Int = 0
var incrementTime = NSDate()
struct Instrumentation {
var title: String
var point: Int
var elapsedTime: Double
init(_ title: String, _ point: Int, _ elapsedTime: Double) {
self.title = title
self.point = point
self.elapsedTime = elapsedTime
}
}
var elapsedTimes = [Instrumentation]()
func instrument(_ title: String) {
increment += 1
let incrementedTime = -incrementTime.timeIntervalSinceNow
let newPoint = Instrumentation(title, increment, incrementedTime)
elapsedTimes.append(newPoint)
incrementTime = NSDate()
}
उपयोग: -
instrument("View Did Appear")
print("ELAPSED TIMES \(elapsedTimes)")
नमूना उत्पादन: -
ELAPSED TIMES [MyApp.SomeViewController.Instrumentation (शीर्षक: "स्टार्ट व्यू डिड लोड", बिंदु: 1, elapsedTime: 0.040504038333892822), MyApp.SomeViewDontroller.Instrumentation (शीर्षक: "समाप्त जोड़ते हुए सब व्यूज़", बिंदु: 2, elapedTime) MyApp.SomeViewController.Instrumentation (शीर्षक: "View Did Appear", बिंदु: 3, elapsedTime: 0.56564098596572876)]
कई उत्तर अजीब हैं और वास्तव में मिलीसेकंड में परिणाम नहीं देते हैं (लेकिन सेकंड या कुछ और में):
यहाँ मैं MS (MILLISECONDS) प्राप्त करने के लिए क्या उपयोग करता हूँ:
स्विफ्ट:
let startTime = NSDate().timeIntervalSince1970 * 1000
// your Swift code
let endTimeMinusStartTime = NSDate().timeIntervalSince1970 * 1000 - startTime
print("time code execution \(endTimeMinStartTime) ms")
उद्देश्य सी:
double startTime = [[NSDate date] timeIntervalSince1970] * 1000.0;
// your Objective-C code
double endTimeMinusStartTime = [[NSDate date] timeIntervalSince1970] * 1000.0 - startTime;
printf("time code execution %f ms\n", endTimeMinusStartTime );
स्विफ्ट 4 के लिए, अपनी कक्षा में एक प्रतिनिधि के रूप में जोड़ें:
public protocol TimingDelegate: class {
var _TICK: Date?{ get set }
}
extension TimingDelegate {
var TICK: Date {
_TICK = Date()
return(_TICK)!
}
func TOCK(message: String) {
if (_TICK == nil){
print("Call 'TICK' first!")
}
if (message == ""){
print("\(Date().timeIntervalSince(_TICK!))")
}
else{
print("\(message): \(Date().timeIntervalSince(_TICK!))")
}
}
}
हमारी कक्षा में जोड़ें:
class MyViewcontroller: UIViewController, TimingDelegate
फिर अपनी कक्षा में जोड़ें:
var _TICK: Date?
जब आप कुछ करना चाहते हैं, तो इसके साथ शुरू करें:
TICK
और के साथ अंत:
TOCK("Timing the XXX routine")