Цель и задачи: Измерение точности работы таймера iPhone. Измерение влияния iOS на скорость работы приложения.
Материалы: iPhone SDK 4.0, XCode 3.2.3, 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
#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 );
}
Еще по теме:
Измерение точности таймера для iPhone и Web [Unity] Порекомендовать: