2012-04-19 8 views
8

He escrito una aplicación para probar el rendimiento de la imagen en iOS. He intentado 3 vistas diferentes, todas mostrando el mismo PNG grande. La primera es una vista que dibuja usando CGContextDrawImage(). El segundo establece self.layer.content. El tercero es un UIImageView simple.UIImageView muestra MUCHO más rápido que CG o CALayer. Alguien sabe por qué?

La imagen utilizada se crea usando - [UIImage initWithContentsOfData:] y se almacena en caché en viewController. Cada prueba asigna una vista repetidamente, la agrega a la jerarquía de vistas y luego la elimina y la libera. Los tiempos se toman desde el inicio de loadView a viewDidAppear y se dan como fps (efectivamente, ver dibujos por segundo).

Estos son los resultados de un iPad 1 ejecutan 5,1 usando una imagen sin escala 912 x 634:

CGContext: 11 fps 
CALayer:  10 fps 
UIImageView: 430 fps (!) 

¿Estoy alucinando? Parece casi imposible que UIImageView pueda dibujar tan rápido, pero en realidad puedo ver las imágenes parpadear. Intenté cambiar entre dos vistas similares para vencer el posible almacenamiento en caché, pero la velocidad de fotogramas era aún mayor.

Siempre había asumido que UIImageView era solo una envoltura para - [CALayer setContent]. Sin embargo, perfilar el UIImageView muestra que casi no hay tiempo invertido en ningún método de dibujo que pueda identificar.

Me encantaría saber qué está pasando. Cualquier ayuda sería muy apreciada.

+1

Modifique su pregunta para incluir el código que ha programado en cada uno de los casos, o un enlace a él. –

+0

El código es parte de una aplicación más grande utilizada para probar nuestro código de juego propietario. Llevará un par de horas extraer los bits relevantes. Mientras tanto, me complacerá contarte sobre los detalles específicos que te faltan en la descripción anterior. –

+0

"Los tiempos se toman desde el inicio de loadView a viewDidAppear" - eso parece un poco falso, ya que se podría llamar a 'viewDidAppear' antes de que la vista realmente aparezca en la pantalla.Si no está obligando a la pantalla a actualizar, realmente no está cronometrando nada útil; puedes crear y destruir varios UIImageViews pero solo uno se dibuja. Me pregunto si UIImageView está configurando el contenido de su capa bajo demanda en '-layoutSubviews', así es como lo haría, para asegurarme de haber tocado la capa solo una vez por cada actualización de pantalla. –

Respuesta

1

Aquí está mi idea.

Cuando modifica una jerarquía de UIView, ya sea agregando, eliminando o modificando alguna vista, aún no se realiza ningún dibujo. En su lugar, la vista se marca con 'setNeedsDisplay', y se vuelve a dibujar la próxima vez que el runloop es libre de dibujar.

De hecho, si su código de prueba es como la siguiente (sólo puedo adivinar):

for (int i=0; i<10000; i++) { 
    UIImageView* imageView = [[UIImageView alloc] initWithFrame:frame]; 
    [mainView addSubview: imageView]; 
    [imageView setImage: image]; 
    [mainView removeSubview: imageView]; 
} 

que el runloop se bloquea hasta que este bucle se realiza. La jerarquía de vistas se dibuja solo una vez, el rendimiento medido es el de asignar e inicializar objetos.

Por otro lado, el CGContextDrawImage() es libre de dibujar de inmediato, creo.

+1

Sí, definitivamente no estoy haciendo eso. Sin embargo, es una suposición razonable. Mi secuencia de prueba vuelve al ciclo de ejecución después de cada paso. Estamos en medio de un gran lanzamiento aquí en Funzio, pero trataré de obtener una copia del proyecto en github mañana temprano. Gracias por la ayuda. –

1

El alto FpS con UIImageView se debe a que en realidad no se vuelve a dibujar, pero solo marca el contenido para volver a dibujar en el futuro cuando UIKit tiene ganas de hacerlo.

Como nota: Lo que es extraño es que el método CGContext es más rápido que el método CALayer. También probé estos métodos en un proyecto mío y trabajar con CALayer es el método más rápido (excepto el uso de OpenGL ES, por supuesto).

Cuestiones relacionadas