2010-03-28 8 views
9

Existe-t-il des astuces d'optimisation standard pour Objective-C pour une exécution plus rapide selon les méthodes habituelles de "inlining" comme en C++ ou la balise "g ++ -fast"? Editer: Quelqu'un at-il un petit exemple utilisant SEL et IMP quand theMethod a deux (ou plus) entiers pour l'entrée?Optimisation Objective-C

+0

Ce sujet est discuté en détail ici: http://www.mulle-kybernetik.com/artikel/Optimization/ – codewarrior

+1

Dans un cadre de haut niveau comme le cacao, les optimisations les plus petits comme celui-ci sont une perte de temps (autre que de changer les paramètres du compilateur), car beaucoup de classes fondamentales sont déjà fortement optimisées. Vous devriez seulement optimiser si le profilage montre que quelque chose prend beaucoup de temps supplémentaire. – shosti

Répondre

12

Voici une petite optimisation qui ne vaut pas vraiment le temps d'être mise en œuvre, et que je n'utilise jamais personnellement, mais je suppose que c'est toujours bon à savoir. Plutôt que d'envoyer à plusieurs reprises le même message au même objet, vous pouvez contourner l'envoi répété de méthodes en utilisant directement l'implémentation de la méthode. Par exemple, au lieu de:

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

Vous pouvez essayer:

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

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

Cela signifie que la recherche de méthode est effectuée qu'une seule fois et vous pouvez appeler la méthode directement par la valeur retournée IMP. Toutes les implémentations de méthode Objective-C prennent au moins deux arguments, le premier argument est l'objet récepteur de type id, qui devient self dans l'implémentation de la méthode, et le second argument est le sélecteur [de type SEL] qui a été utilisé pour déterminer la méthode implémentation, et devient _cmd dans l'implémentation de la méthode.

Cette approche peut rapidement se dégrader si vous n'utilisez pas la bonne définition de fonction “ ” (je ne me souviens pas du terme approprié). IMP est un typedef pour une fonction qui renvoie void* et prend (id,SEL,...) comme arguments. Cela peut rendre difficile à utiliser si la méthode renvoie effectivement quelque chose d'autre comme float. Pour vous aider à ce sujet, vous pouvez lancer la valeur de retour de -methodForSelector:, comme ceci:

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

Avec certains soins, vous pouvez enregistrer le theMethod et vous pourrez peut-être utiliser pour toutes les instances d'une classe particulière, pas seulement un exemple, mais marchez prudemment.

+6

Comme avec la plupart des éléments de performance, vous devez exécuter Instruments sur votre code pour voir où se trouvent les goulots d'étranglement. Les articles ci-dessus sont super ... si vous en avez besoin. Si vous ne le faites pas, cela rend le code difficile à lire. – nall

+2

@nall: Absolument. J'ai fait quelques benchmarks de base, et dans des boucles serrées comme ci-dessus, le contournement de l'expédition a entraîné environ la moitié du temps d'exécution ('theMethod' a fait quelques calculs de base). Si vous passez beaucoup de temps dans 'objc_msgSend' (ou quelle que soit la méthode appelée de nos jours), alors contournement de dispatch peut être une option, sinon, comme vous le dites, ce sera plus une obfuscation qu'une optimisation. – dreamlax

+0

C'est une optimisation vraiment intéressante, mais ne serait-il pas plus facile de simplement faire une fonction C au lieu d'obtenir l'IMP d'une méthode? – shosti

9

L'optimisation est mieux gérée par le compilateur. Les Mac utilisent GCC, donc l'indicateur GCC d'optimisation standard (-0 niveau) devrait fonctionner. Dans XCode, vous pouvez définir le niveau d'optimisation dans project settings. Si vous n'utilisez pas GCC, consultez la documentation du compilateur pour savoir comment activer l'optimisation.

Mise à jour: XCode 4 utilise le backend LLVM par défaut. Les interfaces GCC et clang utilisent les indicateurs d'optimisation "-O n". Pour GCC, n est un nombre entier compris entre 0 et 3, ou "s" ou (Apple uniquement) "z". Pour clang, n est un nombre entier de 0 à 4, ou "s".

+0

C'est vrai - hors de la mémoire c'est réglé sur [-O3] – SK9

+0

Un grand merci à tous pour vos suggestions et votre temps! Si vous le souhaitez, pouvez-vous donner un court exemple en utilisant SEL et IMP lorsque theMethod prend deux (ou plus) entiers comme entrée. – SK9

+0

@SpecialK: un petit exemple de * quoi *? Vouliez-vous faire un commentaire sur la réponse de dreamlax? – outis