2010-03-28 20 views
9

¿Hay trucos de optimización estándar para Objective-C para hacer una ejecución más rápida en la línea de "inline" métodos frecuentes como en C++ o la etiqueta "g ++ -Rápida"?optimización de Objective-C

Editar: ¿Alguien tiene un ejemplo corto usando SEL e IMP cuando theMethod tiene dos (o más) para la entrada de números enteros?

+0

Este tema se discute en gran detalle aquí: http://www.mulle-kybernetik.com/artikel/Optimization/ – codewarrior

+1

En un marco de alto nivel como el cacao, la mayoría pequeñas optimizaciones como este son una pérdida de tiempo (además de cambiar la configuración del compilador), ya que muchas clases fundamentales ya están muy optimizadas. Solo debe optimizar si los perfiles muestran que algo está tomando mucho tiempo extra. – shosti

Respuesta

12

He aquí una pequeña optimización que en realidad no puede valer la pena el tiempo para poner en práctica, y uno que nunca uso personal, pero todavía adivinar bueno conocer. En lugar de enviar repetidamente el mismo mensaje al mismo objeto una y otra vez, puede omitir el envío repetido de métodos mediante el uso directo de la implementación del método. Por ejemplo, en lugar de:

for (int i = 0; i < 100000000; i++) 
    [someObject messageWithInt:i]; 

Usted podría intentar:

SEL theSelector = @selector(messageWithInt:); 
IMP theMethod = [someObject methodForSelector:theSelector]; 

for (int i = 0; i < 100000000; i++) 
    theMethod (someObject, theSelector, i); 

Esto significa que las operaciones de búsqueda método sólo se realiza una vez y se puede invocar el método directamente a través del IMP valor devuelto. Todas las implementaciones método objetivo-C toman al menos dos argumentos, el primer argumento es el objeto receptor de tipo id, que se convierte self dentro de la implementación del método, y el segundo argumento es el selector [de tipo SEL] que se utilizó para determinar el método implementación, y se convierte en _cmd en la implementación del método.

Este enfoque puede agriarse rápidamente si no utiliza la definición de función “ correcta ” (no recuerdo el término adecuado). IMP es una typedef para una función que devuelve void* y toma como argumentos (id,SEL,...). Esto puede dificultar el uso si el método realmente devuelve algo más como float. Para ayudar en esta materia, se puede convertir el valor devuelto de -methodForSelector:, así:

typedef float (*MyMethodIMP)(id,SEL,int); 

SEL theSel = @selector(messageWithInt:); 
MyMethodIMP theMethod = (MyMethodIMP)[someObject methodForSelector:theSel]; 
float result = 0.0; 

for (int i = 0; i < 100000000; i++) 
    result += theMethod (someObject, theSel, i); 

Con un poco de cuidado, puede guardar el theMethod y usted puede ser capaz de utilizarlo para todas las instancias de una clase en particular, no solo una instancia, sino que pise con cuidado.

+6

Al igual que con la mayoría de los elementos de rendimiento, debe ejecutar Instruments en su código para ver dónde están los cuellos de botella. Los artículos anteriores son geniales ... si los necesitas. Si no lo hace, solo hace que el código sea difícil de leer. – nall

+2

@nall: Absolutamente. Hice algunos benchmarking básicos, y en bucles apretados como el anterior, eludir el despacho resultó en aproximadamente la mitad del tiempo de ejecución ('theMethod' hizo algunas matemáticas básicas). Si se gasta mucho tiempo en 'objc_msgSend' (o como se llame el método en estos días), omitir el envío puede ser una opción, de lo contrario, como dices, será más una ofuscación que una optimización. – dreamlax

+0

Esa es una optimización realmente interesante, pero ¿no sería más fácil simplemente hacer una función C en lugar de obtener el IMP de un método? – shosti

9

La optimización se maneja mejor por el compilador. Los Mac utilizan GCC, por lo que debería funcionar la bandera de GCC de optimización estándar (-O nivel). En XCode, puede establecer el nivel de optimización en project settings. Si no está utilizando GCC, consulte la documentación del compilador para saber cómo habilitar la optimización.

Actualización: XCode 4 utiliza el backend LLVM por defecto. Tanto GCC como las interfaces de clang utilizan indicadores de optimización "-O n". Para GCC, n es un número entero de 0 a 3, o "s" o (solo Apple) "z". Para clang, n es un número entero de 0 a 4, o "s".

+0

Correcto, la memoria está configurada en [-O3] – SK9

+0

¡Muchas gracias a todos por sus sugerencias y tiempo! Si está dispuesto, ¿puede dar un pequeño ejemplo usando SEL e IMP cuando el Método toma dos (o más) enteros como entrada? – SK9

+0

@SpecialK: un breve ejemplo de * qué *? ¿Quisiste comentar sobre la respuesta de dreamlax? – outis