Элементарные способы измерения времени выполнения метода - PullRequest
5 голосов
/ 24 октября 2009

Какой объект / метод я бы вызвал, чтобы получить текущее время в миллисекундах (или большую точность), чтобы помочь измерить, сколько времени потребовалось для выполнения метода?

NSDate timeIntervalSinceDate вернет NSInterval, который измеряется в секундах. Я ищу что-то более мелкозернистое, что-то похожее на Java System.currentTimeMillis.

Есть ли эквивалентная версия в target-c / CocoaTouch?

Ответы [ 7 ]

25 голосов
/ 24 октября 2009

Для очень тонкой синхронизации в OS X я использую mach_absolute_time( ), который определен в <mach/mach_time.h>. Вы можете использовать его следующим образом:

#include <mach/mach_time.h>
#include <stdint.h>

static double ticksToNanoseconds = 0.0;

uint64_t startTime = mach_absolute_time( );
// Do some stuff you want to time here
uint64_t endTime = mach_absolute_time( );

 // Elapsed time in mach time units
uint64_t elapsedTime = endTime - startTime;

// The first time we get here, ask the system
// how to convert mach time units to nanoseconds
if (0.0 == ticksToNanoseconds) {
    mach_timebase_info_data_t timebase;
    // to be completely pedantic, check the return code of this next call.
    mach_timebase_info(&timebase);
    ticksToNanoseconds = (double)timebase.numer / timebase.denom;
}

double elapsedTimeInNanoseconds = elapsedTime * ticksToNanoseconds;
9 голосов
/ 24 октября 2009

На самом деле, +[NSDate timeIntervalSinceReferenceDate] возвращает NSTimeInterval, который является typedef для double. Документы говорят

NSTimeInterval всегда указывается в секундах; он дает точность до миллисекунды в диапазоне 10 000 лет.

Так что это безопасно для синхронизации с точностью до миллисекунды. Я делаю это все время.

4 голосов
/ 24 октября 2009

Не используйте для этого NSDate. Вы теряете много точности для вызова методов и создания объектов, возможно, даже выпуская что-то внутреннее. Вам просто не хватает контроля.

Используйте либо time.h, либо Стивен Кэнон предложил mach/mach_time.h. Они оба гораздо точнее.

Лучший способ сделать это - запустить Инструменты или Акулу, прикрепить их к вашему процессу (работает, даже если он уже запущен) и позволить им измерить время, которое занимает метод.

После того, как вы ознакомитесь с ним, это займет даже меньше времени, чем любое решение "вставь в машинное время-функции-и-перекомпилируй все приложение". Вы даже получаете много дополнительной информации. Я бы не стал соглашаться на меньшее.

2 голосов
/ 24 октября 2009

timeIntervalSinceReferenceDate отлично.

Однако, если это не длительный метод, это не принесет особого плода. Время выполнения может сильно отличаться, если вы говорите о нескольких миллисекундах. Если ваш поток / процесс будет прерван в середине пути, у вас будут недетерминированные всплески. По сути, ваш размер выборки слишком мал. Используйте профилировщик или выполните 100 000 итераций, чтобы получить общее время, и разделите на 100 000, чтобы получить среднее время выполнения.

1 голос
/ 24 января 2012

Я опубликую свой ответ из другого поста здесь. Обратите внимание, что мое по общему признанию простое решение этой сложной проблемы использует NSDate и NSTimeInterval в качестве основы:


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

Лучше всего проверить мою запись в блоге по этому вопросу: Сроки в 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 голос
/ 24 октября 2009

Если вы пытаетесь настроить производительность своего кода, вам лучше использовать инструменты или Shark, чтобы получить общее представление о том, где ваше приложение тратит свое время.

0 голосов
/ 15 сентября 2012

@ bladnman Мне нравится ваш секундомер ... Я использую его все время .. Вот небольшой блок, который я написал, который устраняет необходимость в закрытом вызове и делает его еще более легким (если это даже казалось возможным) в использовании, лол.

+(void)stopwatch:(NSString*)name timing:(void(^)())block {
    [MMStopwatch start:name];
    block();
    [MMStopwatch stop: name];
}

тогда вы можете просто позвонить куда угодно ..

[MMStopwatch stopwatch:@"slowAssFunction" timing:^{
    NSLog(@"%@",@"someLongAssFunction");
}]; 

someLongAssFunction

-> Stopwatch: [slowAssFunction] runtime:[0.054435]

Вы должны опубликовать эту присоску на github - чтобы люди могли легко найти ее / внести свой вклад и т. Д. Это здорово. спасибо.

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