Вы заметили, что dispatch_after работает на 10% медленнее на устройствах iOS?
В последнее время я использовал dispatch_after вместо executeSelector: withObject: afterDelay, когда я хочу вызвать некоторый код после задержки. Код чище, у него есть доступ к закрытой области видимости, я могу поместить код в строку вместо написания одноразового метода и т. Д. И т. Д.
Мой код может выглядеть так:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
delay * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
//Delayed-execution code goes here.
}
);
Однако недавно я обнаружил, что время выполнения этого кода, по-видимому, работает примерно на 10% медленнее, чем запрошено. Если я запрашиваю задержку в 10 секунд, мой блок исполняется примерно через 11 секунд. Это на устройстве iOS. Кажется, что времена на симуляторе совпадают.
Код, который я использую для тестирования, довольно прост:
NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
delay * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
NSTimeInterval actualDelay = [NSDate timeIntervalSinceReferenceDate] - startTime;
NSLog(@"Requested delay = %.3f. Atual delay = %.3f", delay, actualDelay);
//Delayed-execution code goes here.
}
);
Я тестировал на устройствах от iOS 4S до iPad Air, и дополнительная задержка довольно стабильна. Я еще не тестировал на старых устройствах, таких как iPhone 4 или iPad 2, хотя скоро сделаю это.
Я мог бы ожидать 20–50 мс «спада» в задержке, но постоянное превышение на 10–11% является странным.
Я добавил в свой код «коэффициент выдумки», который корректирует дополнительную задержку, но я нахожу это удивительным:
#define delay_fudge 0.912557 //Value calculated based on averages from testing.
NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
delay * delay_fudge * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
NSTimeInterval actualDelay = [NSDate timeIntervalSinceReferenceDate] - startTime;
NSLog(@"Requested delay = %.3f. Actual delay = %.3f", delay, actualDelay);
//Delayed-execution code goes here.
}
);
Я, вероятно, должен сделать больше анализа и посмотреть, есть ли фиксированное увеличение задержки плюс коэффициент задержки или прямая процентная задержка, или, возможно, некоторая нелинейная шкала ошибки, но сейчас простой множитель, кажется, работает довольно хорошо.