iPhoneСтатьиПрограммирование

[iPhone, XCode] Измерение точности таймера iPhone

Автор:

Цель и задачи: Измерение точности работы таймера iPhone. Измерение влияния iOS на скорость работы приложения.
Материалы: XCode 3.2.3, iPhone SDK 4.0, iPod Touch 3G, iOS 3.1.3

Самый точный таймер на iPhone: mach_absolute_time().
По виду выглядит очень похоже на QueryPerformanceCounter из Windows, тоже возвращает время в попугаях. Чтобы привести показания к человеческому времени, есть функция mach_timebase_info().

Делаем простую вещь: вызываем 10 раз подряд mach_absolute_time(), считаем сколько прошло времени между вызовами и смотрим на разброс значений. Таким образом определяем точность таймера.

Второе: 10 раз крутим длинный цикл, внутри которого делаем простые вещи (например, постоянно увеличиваем переменную) и считаем сколько времени занимает этот длинный цикл. Если разброс времени сильно больше точности таймера - то это время кто-то у нас украл. Ясно кто - многозадачная операционная система.

Перед всеми замерами подождем 5 секунд, чтобы минимизировать влияние операционной системы (которая после запуска приложения делает анимацию раскрытия окна).

Замеры делаем минимум четыре раза. Сборка Release.

На симуляторе (Core2Duo 2.66Ghz) такие цифры: узнать показания таймера = 27..30 наносекунд, точность таймера = 3 наносекунды (миллиард наносекунд = 1 секунде, свет за 1 наносекунду пройдет всего 30 см).
MacOS ворует от 0,05 до 0,33 % времени вне зависимости от длинны цикла.

Но, симулятор это не интересно, пробуем на iPod Touch 3G (предварительно выключив и включив его).
Узнать показания таймера: 1208..1416 наносекунды.
Средняя точность таймера: 125 наносекунды, худшая 209 наносекунд.
Влияние iOS: от 0,5 и аж до 12 %, в среднем 1 %.

Ни разные стройки компилятора, ни запуск сразу с устройства - не оказал существенного влияния на точность таймера.

#import <mach/mach_time.h>

#define LOOP_COUNT 10000000

mach_timebase_info_data_t info;

void PrintResult ( uint64_t * time );


int main () 
{
    mach_timebase_info ( & info );

    // подождем 5 секунд
    const uint64_t start = mach_absolute_time ();
    while ( (mach_absolute_time () - start) * info.numer / info.denom < 5000000000 )
    {}
  
    uint64_t time_loop [10];
    uint64_t time [10];
  
    // посчитаем время десяти длинных циклов
    time_loop [0] = mach_absolute_time ();
    for ( int i = 1; i < 10; ++i )
    {
        for ( volatile int j = 0; j < LOOP_COUNT; ++j )
        {}

        time_loop [i] = mach_absolute_time ();
    }

    // посчитаем время mach_absolute_time
    time [0] = mach_absolute_time ();
    time [1] = mach_absolute_time ();
    time [2] = mach_absolute_time ();
    time [3] = mach_absolute_time ();
    time [4] = mach_absolute_time ();
    time [5] = mach_absolute_time ();
    time [6] = mach_absolute_time ();
    time [7] = mach_absolute_time ();
    time [8] = mach_absolute_time ();
    time [9] = mach_absolute_time ();

    // результаты
    NSLog ( @"long loop:" );
    PrintResult ( time_loop );

    NSLog ( @"mach_absolute_time:" );
    PrintResult ( time );
    return 0;
}


void PrintResult ( uint64_t * time )
{
    uint64_t min = UINT64_MAX, max = 0, avg = 0;
  
    for ( int i = 0; i < 9; ++i )
    {
        const uint64_t dt = (time [i+1] - time [i]) * info.numer / info.denom;
        NSLog ( @"delta %i: %lld nanoseconds", i, dt );
        if ( dt > max )
            max = dt;
        if ( dt < min )
            min = dt;
        avg += dt;
    }
    avg /= 9;
    NSLog ( @"max = %lld, min = %lld, average = %lld, max delta = %lld, %% delta = %f", max, min, avg, max - min, 100.0f * (max-min) / avg );
}


--
http://pshenichny.livejournal.com/28961.html

#iPhone, #XCode

24 сентября 2010