porque plus muy lento esta ios objective-c objective-c-blocks grand-central-dispatch

ios - plus - porque mi iphone 4 es muy lento



¿Ha notado que dispatch_after se ejecuta ~ 10% demasiado lento en los dispositivos iOS? (1)

Es posible que haya escuchado sobre la combinación de temporizador y la siesta de la aplicación , lo que ayuda a reducir el consumo de energía.

Lo que está observando aquí es el efecto de retrasar los eventos del sistema hasta un cierto "valor de margen de maniobra" para poder ejecutarlos todos juntos en un punto en el tiempo, "Temporizador de fusión". Eso aumentará la duración de la CPU en su modo de reducción de energía.

Para el envío lib, hay una bandera que se puede utilizar para aumentar la precisión del "valor de margen de maniobra", que también afecta eventualmente la precisión de un temporizador (ver más abajo). No creo que sea una buena idea hacer que los cronómetros sean innecesariamente precisos, por ejemplo, para dispositivos móviles.

Mi sospecha es que dispatch_after usará un temporizador de despacho con un cierto conjunto de valores de margen de maniobra, que está definido por la implementación.

Puede implementar temporizadores bastante precisos con lib de despacho, utilizando dispatch_source_set_timer() , donde también puede especificar el "valor de margen de maniobra".

Véase también: dispatch/source.h

/*! * @typedef dispatch_source_timer_flags_t * Type of dispatch_source_timer flags * * @constant DISPATCH_TIMER_STRICT * Specifies that the system should make a best effort to strictly observe the * leeway value specified for the timer via dispatch_source_set_timer(), even * if that value is smaller than the default leeway value that would be applied * to the timer otherwise. A minimal amount of leeway will be applied to the * timer even if this flag is specified. * * CAUTION: Use of this flag may override power-saving techniques employed by * the system and cause higher power consumption, so it must be used with care * and only when absolutely necessary. */ #define DISPATCH_TIMER_STRICT 0x1 ... * Any fire of the timer may be delayed by the system in order to improve power * consumption and system performance. The upper limit to the allowable delay * may be configured with the ''leeway'' argument, the lower limit is under the * control of the system. *

Últimamente he estado usando dispatch_after en lugar de performSelector: withObject: afterDelay cuando quiero activar algún código después de un retraso. El código está más limpio, tiene acceso al ámbito de aplicación adjunto, puedo poner el código en línea en lugar de escribir un método desechable, etc., etc.

Mi código podría verse así:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ //Delayed-execution code goes here. } );

Sin embargo, recientemente descubrí que el tiempo de excitación de este código parece funcionar de manera bastante constante, aproximadamente un 10% más lento de lo solicitado. Si pido un retraso de 10 segundos, mi bloqueo se ejecuta unos 11 segundos más tarde. Esto es en un dispositivo iOS. Los tiempos parecen coincidir bastante en el simulador.

El código que estoy usando para probar esto es bastante simple:

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. } );

He probado en dispositivos desde un iOS 4S a un iPad Air y el retraso adicional es bastante constante. Todavía no he probado en un dispositivo más antiguo como un iPhone 4 o un iPad 2, aunque lo haré pronto.

Podría esperar 20-50 ms de "pendiente" en la demora, pero un exceso constante del 10% al 11% es impar.

He agregado un "factor de fudge" a mi código que se ajusta al retraso adicional, pero me parece sorprendente:

#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. } );

Probablemente debería hacer más análisis y ver si hay un aumento fijo en el retardo más un factor de retardo o un porcentaje de retardo directo, o quizás alguna escala no lineal al error, pero por ahora parece que un simple multiplicador funciona bastante bien.