9
votes

La performance est-elle affectée par l'ajout de catégories à une classe

Je suis nouveau à Cocoa et j'ai une petite question avant que je ne sois emporté d'utilisation de catégories.

Dites que vous ajoutez une nouvelle méthode à Nstring. Cela affecte-t-il les performances des messages Nstring normaux ou des méthodes de catégorie uniquement vérifiées lorsqu'un appel de méthode ne correspond pas à la méthode standard définie?


0 commentaires

3 Réponses :


4
votes

Si vous êtes nouveau à Cocoa, cela ne devrait pas être quelque chose que vous vous inquiétez. Outre la règle de base de ne pas faire d'hypothèses sur la performance sans profilage.

Si vous devez fournir des fonctionnalités, vous l'ajoutez où vous pouvez. S'il est logique d'étendre une classe, faites-le. Si vous n'ajoutez pas la fonctionnalité à Nstring, vous devez lui fournir ailleurs. Si vous le faites dans une autre classe, cela ajoute un niveau de complexité différent.

Personnellement, je m'inquiéterais de la conception de votre application. Utilisez une catégorie si cela a du sens, et si vous êtes vraiment préoccupé par la performance, profilez votre application une fois que cela fonctionne.

Et bien que je prête une hypothèse ici, je dirais qu'il y aurait plus de gros succès à la performance de votre application que la rapidité des appels vers Nstring. Sauf si vous faites un lot d'appels Nstring - auquel cas nous sommes de retour au profilage à nouveau.


4 commentaires

Votre droit je suis nouveau à objc, je dois m'en soucier car je fais des centaines de millions d'appels vers des objets Nstring. Ont déjà dû convertir un certain code pour utiliser c structs C à la place. (:


Dans des cas comme celui-ci, la surcharge associée à l'utilisation d'objets est probablement le coupable, et non des ralentissements que vous devinez peut être causé par l'ajout de méthodes via des catégories.


D'accord. Nstrings ne sont pas des démons de performance. Pour des centaines de millions d'appels, je prendrais certainement la peine de passer à Carstrings (et probablement cadrays si vous utilisez Nsarray). Profil comme Abizem dit, mais l'expérience indique que sur cet ordre de grandeur, vous avez besoin de C. Il suffit de terminer à l'intérieur d'un objet afin que les structures de données C ne se répandent pas dans votre ensemble de programme et vous pouvez optimiser leurs performances internes sans réécriter. votre programme.


-1 Bien que le profilage soit la seule chose qui puisse déterminer la vérité empirique ultime, car les deux autres réponses démontrent, vous pouvez toujours répondre à la question, bien que les implications réelles puissent être légèrement différentes. Mais je suis en train de descendre parce que vous ne répondez pas à la question.



8
votes

Toutes les méthodes sont envoyées à l'aide d'une expédition dynamique, aux messages aux méthodes de catégorie n'interfèrent pas avec les messages "normaux".

À partir d'un aspect de performance, les poignées d'exécution associant les méthodes avec la classe en question. Il existe donc un coût unique pour cela, mais il n'y a pas de changement à chaque objet individuel. Je ne serais pas préoccupé par la performance avec les catégories, mais il serait prudent de veiller à ce que les méthodes que vous ajoutez via des catégories n'incluent pas les méthodes par défaut ou celles spécifiées dans d'autres catégories. C'est là que les problèmes commencent généralement.


5 commentaires

Ceux-ci ont-ils un sens pour les catégories Nstring? '(Nstring *) FirstStringBetween: Démarrer et: fin' '(Nsarray *) Stringsbetween: Démarrer et: finir' Ie [String Strinsbetween: @ "(" et @ ")"]


Ceux-ci semblent être des noms d'accord, bien qu'ils ne soient pas aussi détaillés que possible, et je m'attendrais à ce que la documentation compense cela. Tant que vous savez ce qu'ils veulent dire, cependant ... En général, j'examinerais les noms des méthodes de cacao existantes et j'utilise le modèle qu'ils le font.


Le moyen le plus simple d'éviter les collisions de nom de méthode consiste à ajouter un préfixe à toutes les méthodes de la catégorie. Xyzfirstringbetween: ...


C'est vrai, mais cela viole la bonne conception de noms de méthodes. Je suis d'avis que connaissant le potentiel de conflit peut aider à éviter de tels problèmes. Les programmeurs qui ajoutent des catégories à des classes largement utilisées doivent être particulièrement méfiants des pièges potentiels. Cela dit, tout ce qui est meilleur que quelque chose qui ne fonctionne pas. :-)


Le problème avec des méthodes de catégorie bien nommées est qu'ils sont ceux qui sont principalement susceptibles de colliser avec Apple. J'avais juste que cela se produise lorsque j'ai ajouté --Pop à NsmutableArray et UinaviagtionController a explosé. Leçon: les bons noms sont bons et je déteste les préfixes sur les méthodes, mais juste un peu bizarre peut être meilleur pour les catégories sur des objets Apple. Personnellement, je pense que c'est un bug que Apple ajoute des méthodes privées sans préfixer avec le soulignement. Je devrais radar que. Mais ils le font un lot .



7
votes

en général, no.

objc_msgsend () garde un cache de pseudo-moindre récemment utilisé du plus récent sel à IMP des recherches par classe. Comme toujours, les spécificités sont des «détails privés de mise en œuvre», mais il est raisonnable de dire que le temps de recherche est ~ O (1) en moyenne, quel que soit le nombre de sélecteurs. La manière la plus courante que cela se fait est avec une petite table de hachage - si le sélecteur est dans le cache, l'envoi est essentiellement instantané. Si le sélecteur n'est pas dans le cache, il doit exécuter la recherche chère 'lente path' '.

Cependant, même le «chemin lent» peut être raisonnablement rapide. Il existe un nombre de structures de données que l'on peut se tourner vers, telle que les arbres noirs rouges, qui offrent d'excellents temps de recherche sous-exponentielle qui ont bien échelonnant quel que soit le nombre de sélecteurs - généralement dans le O (log2 (sélectorcount)) < / code> plage. Encore une fois, comment libobjc traite de ce type de détails sont privés, mais il y a tellement de structures de données qui ont facilement échuant quel que soit le nombre d'éléments à rechercher qu'il n'y a aucune raison que ce genre de chose devrait même être sur votre radar.

Une vérification rapide via nm active 7771 sélecteurs dans la fondation et 27510 Sélecteurs dans AppKit, pour un total de 35281 sélecteurs juste entre les deux. Lancer Quicktime, Coredata, Webkit, Quartz et vous avez facilement jusqu'à 50 000 sélecteurs. Avec un taux de croissance du temps log2 , Doublage du nombre de sélecteurs augmentera le pire des cas de moins de 10%.

en résumé: objc_msgsend () utilise un petit cache de hasch pour fournir o (1) temps de recherche pour les plus récents sélecteurs utilisés ... et il y a un De très haut degré de localité temporelle, la grande majorité des dépêches sont complétées dans O (1) Heure indépendamment du nombre de sélecteurs présents dans le système. L'effet naturel du cache est de se "syntoniser" à vos habitudes d'utilisation particulières. Même sur une cache Miss, il est probablement raisonnable de deviner que le temps de recherche de cas de cas est ~ O (log2 (sélecteur) lié, qui est plutôt bon, et c'est probablement mieux que cela dans la pratique.

Pour ce que ça vaut la peine, j'ai passé beaucoup de temps à modifier le code pour la vitesse. Même sur des trucs multi-threading où je vous attachez à tous les CPU faisant d'énormes quantités d'analyse -> Nsview / OpenGL Rendu lourd Rendu, tout codé dans l'objectif-C, je ne verrai que objc_msgsend () prise 1-4 pour cent de la CPU lorsqu'il est profilé avec Shark.app ... et c'est le pire des cas, faisant de l'expédition de messages de l'objectif et de l'objectif. Cela n'a jamais été un problème pour moi et quelle que soit la pénalité de vitesse mineure, elle est composée de 100 fois la productivité de la programmation, facilement.

Voir aussi:

Mulle Kybernetik - Optimisation Obj-C: plus rapide objc_msgsend
Guide de programmation d'exécution de l'objectif-C 2.0 - Messagerie
Apple Objective-C Runtime - objc4-437.tar.gz

EDIT : Quelle bizarrerie est-ce génie: brevet 5960197 - Fonction d'expédition compilateur pour l'objet orienté objet C . Je ne peux pas dire que je savais que tout le système d'expédition du message Obj-C était breveté ... Je suppose que vous pouvez vraiment obtenir un brevet sur n'importe quoi. Je vais aller breveter l'alphabet et accuser grand, bébé!


1 commentaires

+1 Très belle explication des détails de la mise en œuvre probables (si non documentés).