Как записать время выполнения метода точно в миллисекундах? - PullRequest
211 голосов
/ 25 января 2010

Есть ли способ определить, сколько времени необходимо выполнить методу (в миллисекундах)?

Ответы [ 20 ]

422 голосов
/ 25 января 2010
NSDate *methodStart = [NSDate date];

/* ... Do whatever you need to do ... */

NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);

Swift:

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)")

Простота в использовании и точность до миллисекунды.

247 голосов
/ 01 апреля 2013

Вот два однострочных макроса, которые я использую:

#define TICK   NSDate *startTime = [NSDate date]
#define TOCK   NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])

Используйте это так:

TICK;

/* ... Do Some Work Here ... */

TOCK;
48 голосов
/ 25 января 2010

Для детальной синхронизации в 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;

Конечно, применяются обычные предостережения о мелкозернистых измерениях; вам, вероятно, лучше всего многократно вызывать тестируемую процедуру и усреднять / брать минимальную / какую-то другую форму обработки.

Кроме того, обратите внимание, что вы можете найти более полезным профиль ваше приложение, запущенное с использованием инструмента, такого как Shark. Это не даст вам точную информацию о времени, но сообщит вам, на что процент времени приложения тратится, где, что часто более полезно (но не всегда).

12 голосов
/ 22 января 2015

В Swift я использую:

В моем Macros.swift я только что добавил

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()
  • этот код основан на переводе кода Рона на Свифта, он имеет кредит
  • Я использую дату начала на глобальном уровне, любые предложения по улучшению приветствуются
9 голосов
/ 24 января 2012

Я знаю, что это старый, но даже я снова забрел мимо него, так что я решил добавить свой вариант здесь.

Лучше всего проверить мой пост на этом: Временные параметры в Objective-C: секундомер

По сути, я написал класс, который перестает смотреть в основном виде, но инкапсулирован так, что вам нужно только сделать следующее:

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

И в итоге вы получаете:

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

в журнале ...

Снова, посмотрите мой пост немного подробнее или скачайте его здесь: MMStopwatch.zip

8 голосов
/ 21 декабря 2018

Существует удобная оболочка для 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);

Swift

let startTime = CACurrentMediaTime()
// Do your stuff here
let endTime = CACurrentMediaTime()
print("Total Runtime: \(endTime - startTime) s")
7 голосов
/ 25 января 2016

Я использую макросы на основе решения Рона .

#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

4 голосов
/ 30 сентября 2014

Я использую очень минимальную реализацию класса одной страницы, вдохновленную кодом из этого поста в блоге :

#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"]; после финиша, чтобы получить время
3 голосов
/ 02 января 2014

Вы можете получить действительно точное время (секунды.части секунд), используя этот класс StopWatch. Он использует высокоточный таймер в iPhone. Использование NSDate только даст вам вторую точность. Эта версия разработана специально для autorelease и target-c. У меня есть версия 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.

Пример функции A (синхронизация вызова исполнения)

-(void)SomeFunc
{
   StopWatch* stopWatch = [StopWatch stopWatch];
   [stopWatch Start];

   ... do stuff

   [stopWatch StopWithContext:[NSString stringWithFormat:@"Created %d Records",[records count]]];
}
2 голосов
/ 25 января 2010

Я использую это:

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);

Но я не уверен насчет CLOCKS_PER_SEC на iPhone. Возможно, вы захотите оставить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...