Вы заметили, что 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.
  }
);

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

Ответы на вопрос(1)

Ваш ответ на вопрос