Mon application iPhone aura-t-elle un impact sur les performances si j’utilise Objective-C pour un code de bas niveau?

Lorsque vous programmez une application gourmande en ressources processeur ou gourmande en GPU sur l’iPhone ou un autre matériel portable, vous devez prendre des décisions judicieuses en matière d’algorithme pour accélérer votre code.

Mais même les bons choix d’algorithmes peuvent être lents si le langage que vous utilisez fonctionne moins bien qu’un autre.

Existe-t-il des données concrètes comparant Objective-C à C ++, en particulier sur l’iPhone, mais peut-être uniquement sur le bureau Mac, pour des performances linguistiques différentes? Je suis très familier avec cet article comparant C et Objective-C , mais il s’agit d’une question plus vaste de comparaison de deux langages orientés object.

Par exemple, une recherche de vtable C ++ est-elle vraiment plus rapide qu’un message Obj-C? Combien plus rapide? Threading, polymorphism, sorting, etc. Avant de partir en quête d’un projet avec des modèles d’object en double et divers codes de test, je veux savoir si quelqu’un l’a déjà fait et quels sont les résultats. Ce type de test et de comparaison est un projet en soi et peut prendre un temps considérable. Peut-être que ce n’est pas un projet, mais deux et seulement les résultats peuvent être comparés.

Je cherche des données difficiles , pas de l’évangélisation. Comme beaucoup d’entre vous, j’aime et déteste les deux langues pour diverses raisons. De plus, s’il y a quelqu’un qui poursuit activement cette même chose, je serais intéressant de lancer du code pour voir le résultat final, et je suis sûr que d’autres aideraient aussi. Je pense qu’ils ont tous deux des forces et des faiblesses, mon but est de savoir précisément ce qu’ils sont pour qu’ils puissent être évités / exploités dans des scénarios réels.

Mike Ash a quelques chiffres concrets pour la performance de divers appels de méthodes Objective-C par rapport à C et C ++ dans son post “Comparaisons de performances des opérations courantes” . En outre, cette publication de Savoy Software est une lecture intéressante pour optimiser les performances d’une application iPhone en utilisant Objective-C ++.

J’ai tendance à préférer la syntaxe propre et descriptive d’Objective-C à Objective-C ++, et je n’ai pas trouvé que le langage lui-même était à l’origine de goulots d’étranglement. J’ai même tendance à faire des choses qui, je le sais, sacrifient un peu la performance si elles rendent mon code beaucoup plus facile à maintenir.

Oui, bien écrit C ++ est beaucoup plus rapide. Si vous écrivez des programmes critiques pour la performance et que votre C ++ n’est pas aussi rapide que C (ou dans une proportion de quelques pour cent), quelque chose ne va pas. Si votre implémentation ObjC est aussi rapide que C, alors quelque chose ne va pas, c’est-à-dire que le programme est probablement un mauvais exemple de OOD ObjC car il utilise probablement des astuces “sales”. ivar access.

La «comparaison» de Mike Ash est très trompeuse – je ne recommanderais jamais l’approche consistant à comparer les temps d’exécution des programmes que vous avez écrits, ou à la recommander pour comparer C vs C ++ vs ObjC. Les résultats présentés proviennent d’un test avec des optimisations du compilateur désactivées . Un programme compilé avec des optimisations désactivées est rarement pertinent lorsque vous mesurez des temps d’exécution. Pour le voir comme un benchmark qui compare C ++ à Objective-C, il est erroné. Le test compare également des fonctionnalités individuelles, plutôt que des implémentations optimisées complètes du monde réel – les fonctionnalités individuelles sont combinées de manière très différente avec les deux langues. Ceci est loin d’être une référence de performance réaliste pour des implémentations optimisées. Exemples: Avec les optimisations activées , le cache IMP est aussi lent que les appels de fonction virtuels. La dissortingbution statique (par opposition à la dissortingbution dynamic, par exemple en utilisant le virtual ) et les appels aux types C ++ connus (où la dissortingbution dynamic peut être ignorée) peuvent être optimisés de manière agressive. Ce processus est appelé dévirtualisation, et lorsqu’il est utilisé, une fonction membre déclarée virtual peut même être inline d. Dans le cas du test de Mike Ash où de nombreux appels sont faits aux fonctions membres déclarées virtual et à corps vide: ces appels sont totalement optimisés lorsque le type est connu car le compilateur voit l’implémentation et est capable de déterminer la répartition dynamic est inutile. Le compilateur peut également éliminer les appels à malloc dans les versions optimisées (favorisant le stockage de la stack). Ainsi, l’activation des optimisations du compilateur dans C, C ++ ou Objective-C peut entraîner des différences considérables dans les temps d’exécution.

Cela ne veut pas dire que les résultats présentés sont totalement inutiles. Vous pouvez obtenir des informations utiles sur les API externes si vous souhaitez déterminer s’il existe des différences mesurables entre les temps pthread_create dans pthread_create ou +[NSObject alloc] sur une plate-forme ou une architecture par rapport à une autre. Bien entendu, ces deux exemples utiliseront des implémentations optimisées dans votre test (sauf si vous les développez). Mais pour comparer une langue à une autre dans les programmes que vous comstackz… les résultats présentés sont inutiles avec des optimisations désactivées.

Création d’object

Considérez également la création d’objects dans ObjC – chaque object est alloué dynamicment (par exemple sur le tas). Avec C ++, des objects peuvent être créés sur la stack (par exemple, approximativement aussi rapidement que créer une structure C et appeler une fonction simple dans de nombreux cas), sur le tas ou comme éléments de types de données abstraits. Chaque fois que vous atsortingbuez et libérez (par exemple via malloc / free), vous pouvez introduire un verrou. Lorsque vous créez un object C struct ou C ++ sur la stack, aucun verrou n’est requirejs (même si les membres internes peuvent utiliser des allocations de segment de mémoire), il ne coûte souvent que quelques instructions ou quelques instructions plus un appel de fonction.

De même, les objects ObjC sont des instances comptées par référence. Le besoin réel pour un object d’être un std::shared_ptr en performance C ++ critique est très rare. En C ++, il n’est pas nécessaire ni souhaitable de faire de chaque instance une instance comptée de référence partagée. Vous avez beaucoup plus de contrôle sur la propriété et la durée de vie avec C ++.

Tableaux et collections

Les tableaux et de nombreuses collections en C et C ++ utilisent également des conteneurs fortement typés et de la mémoire contiguë. Puisque l’adresse des membres de l’élément suivant est souvent connue, l’optimiseur peut faire beaucoup plus, et vous avez une excellente localisation de cache et de mémoire. Avec ObjC, c’est loin d’être la réalité pour les objects standard (par exemple NSObject ).

Envoi

En ce qui concerne les méthodes, de nombreuses implémentations C ++ utilisent peu d’appels virtuels / dynamics, en particulier dans les programmes hautement optimisés. Ce sont des appels de méthodes statiques et du fourrage pour les optimiseurs.

Avec les méthodes ObjC, chaque appel de méthode (objc message send) est dynamic et constitue par conséquent un pare-feu pour l’optimiseur. En fin de compte, cela entraîne de nombreuses ressortingctions ou inconvénients en ce qui concerne ce que vous pouvez et ne pouvez pas faire pour maintenir les performances au minimum lors de la rédaction des performances critiques d’ObjC. Cela peut entraîner des méthodes plus importantes, la mise en cache de l’IMP, l’utilisation fréquente de C.

Certaines applications en temps réel ne peuvent utiliser aucun message ObjC dans leurs chemins de rendu. Aucun – le rendu audio en est un bon exemple. La répartition ObjC n’est tout simplement pas conçue pour des besoins en temps réel; Les atsortingbutions et les verrous peuvent se produire en arrière-plan lors de la messagerie des objects, ce qui rend la complexité et la durée de la messagerie objc assez imprévisibles pour que le rendu audio manque son délai.

Autres caractéristiques

C ++ fournit également des implémentations de génériques / modèles pour plusieurs de ses bibliothèques. Ceux-ci optimisent très bien. Ils sont de types sûrs et beaucoup de mises en page et d’optimisations peuvent être effectuées avec des modèles (considérez le polymorphism, l’optimisation et la spécialisation qui ont lieu lors de la compilation). C ++ ajoute plusieurs fonctionnalités qui ne sont tout simplement pas disponibles ou comparables en ssortingcte ObjC. Essayer de comparer directement les langs, les objects et les bibliothèques qui sont très différents n’est pas très utile – c’est un très petit sous-ensemble de réalisations réelles. Il est préférable d’étendre la question à une bibliothèque / un cadre ou à un programme réel, en tenant compte de nombreux aspects de la conception et de la mise en œuvre.

Autres points

Les symboles C et C ++ peuvent être plus facilement supprimés et optimisés à différents stades de la construction (décapage, élimination des codes morts, incrustation et incrustation précoce, ainsi que l’optimisation du temps de liaison). Les avantages sont notamment la réduction des tailles binarys, la réduction des temps de lancement et de chargement, la réduction de la consommation de mémoire, etc. Pour une seule application, cela peut ne pas être si grave. mais si vous réutilisez beaucoup de code et que vous devriez le faire, alors vos bibliothèques partagées pourraient append beaucoup de poids inutile au programme, si elles sont implémentées, à moins que vous ne soyez prêt à passer à travers des cercles enflammés. L’évolutivité et la réutilisation sont également des facteurs dans les projets de taille moyenne / grande et les groupes où la réutilisation est élevée.

Bibliothèques incluses

Les implémenteurs de bibliothèques ObjC optimisent également pour l’environnement, de sorte que ses implémenteurs de bibliothèques peuvent utiliser certaines fonctionnalités de langage et d’environnement pour offrir des implémentations optimisées. Bien qu’il existe des ressortingctions assez importantes lors de l’écriture d’un programme optimisé dans pure ObjC, certaines implémentations hautement optimisées existent dans Cocoa. C’est l’un des points forts de Cocoa, bien que la bibliothèque standard C ++ (ce que certains appellent la STL) n’est pas en rest non plus. Cocoa fonctionne à un niveau d’abstraction beaucoup plus élevé que C ++ – si vous ne savez pas bien ce que vous faites (ou devriez faire), opérer plus près du métal peut vous coûter très cher . Revenir à une bonne implémentation de la bibliothèque si vous n’êtes pas un expert dans certains domaines est une bonne chose, à moins que vous ne soyez vraiment prêt à apprendre. De plus, les environnements de Cocoa sont limités; Vous pouvez trouver des implémentations / optimisations qui utilisent mieux le système d’exploitation.

Si vous écrivez des programmes optimisés et que vous avez de l’expérience dans C ++ et ObjC, les implémentations C ++ propres seront souvent deux fois plus rapides ou plus rapides que celles d’ ObjC (oui, vous pouvez comparer à Cocoa). Si vous savez comment optimiser, vous pouvez souvent faire mieux que des abstractions générales de haut niveau. Cependant, certaines implémentations C ++ optimisées seront aussi rapides ou plus lentes que celles de Cocoa (par exemple, ma tentative initiale d’E / S de fichier était plus lente que celle de Cocoa – principalement parce que l’implémentation C ++ initialise sa mémoire).

Cela dépend en grande partie des fonctionnalités linguistiques que vous connaissez. J’utilise les deux langs, ils ont tous deux des forces et des modèles / modèles différents. Ils se complètent assez bien, et il existe d’excellentes bibliothèques pour les deux. Si vous implémentez un programme complexe et performant, l’utilisation correcte des fonctionnalités et des bibliothèques de C ++ vous offrira beaucoup plus de contrôle et offrira des avantages significatifs pour l’optimisation. ne vous attendez pas à gagner à chaque fois, mais sans travail, cependant). Rappelez-vous, il faut des années pour comprendre suffisamment C ++ pour vraiment atteindre ce point.

Je garde la majorité de mes chemins critiques en tant que C ++, mais je reconnais également que ObjC est également une très bonne solution pour certains problèmes, et que de très bonnes bibliothèques sont disponibles.

Il est très difficile de collecter des “données matérielles” pour cela, ce n’est pas une erreur.

Le plus gros problème avec une comparaison de fonctionnalités, comme vous le suggérez, est que les deux langages encouragent des styles de codage très différents. Objective-C est un langage dynamic avec typage de canard, où l’utilisation typique du C ++ est statique. Le même problème d’architecture orientée object aurait probablement des solutions idéales très différentes utilisant C ++ ou Objective-C.

Mon ressenti (comme je l’ai beaucoup programmé dans les deux langages, principalement sur des projets énormes): Pour maximiser les performances d’Objective-C, il faut écrire très près de C. Alors qu’avec C ++, il est possible d’utiliser beaucoup plus le langage sans aucune pénalité de performance par rapport à C.

Quel est le meilleur? Je ne sais pas. Pour des performances pures, C ++ aura toujours l’avantage. Mais le style OOP d’Objective-C a certainement ses avantages. Je pense vraiment qu’il est plus facile de garder une architecture saine avec elle.

Ce n’est vraiment pas quelque chose auquel on peut répondre en général car cela dépend vraiment de la façon dont vous utilisez les fonctionnalités du langage. Les deux langues auront des choses sur lesquelles elles sont rapides, des choses qu’elles sont lentes et des choses parfois rapides et parfois lentes. Cela dépend vraiment de ce que vous utilisez et de la manière dont vous l’utilisez. La seule façon d’être certain est de profiler votre code.

Dans Objective C, vous pouvez également écrire du code c ++. Il est donc plus facile de coder dans Objective C, et si vous trouvez quelque chose qui ne fonctionne pas bien, vous pouvez essayer une version c ++. de cela et voir si cela aide (C ++ tend à optimiser mieux au moment de la compilation). Objective C sera plus facile à utiliser si les API avec lesquelles vous êtes en interface sont également écrites. De plus, vous trouverez que le style de la POO est plus facile ou plus flexible.

En fin de compte, vous devriez aller avec ce que vous savez que vous pouvez écrire du code sûr et robuste et si vous trouvez un domaine qui nécessite une attention particulière de la part de l’autre langue, vous pouvez y passer. X-Code vous permet de comstackr les deux dans le même projet.

J’ai fait quelques tests sur un iPhone 3G il y a près de 2 ans, il n’y avait pas de documentation ou de chiffres difficiles à l’époque. Vous n’êtes pas certain de leur validité, mais le code source est publié et joint.

Ce n’est pas un test très complet, je me suis principalement intéressé à NSArray vs C Array pour itérer un grand nombre d’objects.

http://memo.tv/nsarray_vs_c_array_performance_comparison

http://memo.tv/nsarray_vs_c_array_performance_comparison_part_ii_makeobjectsperformselector

Vous pouvez voir que le tableau C est beaucoup plus rapide aux itérations élevées. Depuis lors, j’ai réalisé que le goulot d’étranglement n’est probablement pas l’itération du NSArray mais l’envoi du message. Je voulais essayer methodForSelector et appeler les méthodes directement pour voir quelle serait la différence, mais je ne l’ai jamais contourné. Selon les tests de Mike Ash, il est 5 fois plus rapide.

Je n’ai pas de données matérielles pour Objective C, mais j’ai un bon endroit pour rechercher du C ++.

C ++ a commencé comme C avec Classes selon Bjarne Stroustroup dans sa reflection sur les premières années de C ++ ( http://www2.research.att.com/~bs/hopl2.pdf ), donc on peut penser à C ++ (comme Objective C ) comme poussant C à ses limites pour l’orientation de l’object.

Quelles sont ces limites? Dans la période 1994-1997, de nombreux chercheurs ont compris que l’orientation dynamic avait un coût pour l’orientation object, par exemple lorsque les fonctions C ++ étaient marquées virtuelles et qu’il pouvait ou non y avoir des classes enfants remplaçant ces fonctions. (Dans Java et C #, toutes les fonctions supposent que les maîtres sont insortingnsèquement virtuels, et il n’ya pas grand chose à faire.) Dans “Étude des techniques de virtualisation pour un compilateur Java juste à temps”, des chercheurs d’IBM Research Tokyo, ils opposent les techniques utilisées pour y faire face, notamment Urz Hölzle et Gerald Aigner. Urz Hölzle, dans un article séparé avec Karel Driesen, avait montré qu’en moyenne, 5,7% du temps passé dans les programmes C ++ (et jusqu’à ~ 50%) était consacré à l’appel de fonctions virtuelles (ex. Vtables + thunks). Plus tard, il a travaillé avec quelques chercheurs de Smalltalk dans ce qui a abouti à la VM Java HotSpot pour résoudre ces problèmes dans OO. Certaines de ces fonctionnalités sont transférées vers C ++ (par exemple, la protection «protégée» et la gestion des exceptions).

Comme je l’ai mentionné, C ++ est un type statique où Objective C est typé en canard. La différence de performance dans l’exécution (mais pas dans les lignes de code) résulte probablement de cette différence.

Cette étude dit que pour vraiment obtenir la performance dans un jeu utilisant beaucoup de CPU, vous devez utiliser C. L’article lié est complet avec un projet XCode que vous pouvez exécuter.

Je crois que l’ essentiel est: Utilisez Objective-C où vous devez interagir avec les fonctions de l’iPhone (après tout, mettre des trampolines partout ne peut être bon pour personne ), mais quand il s’agit de boucles, de classes d’objects vectoriels ou intensives. access au tableau, respectez les tableaux C ++ STL ou C pour obtenir de bonnes performances.

Je veux dire que ce serait complètement idiot de voir position = [[Vector3 alloc] init] ; . Vous ne faites que demander un impact sur la performance si vous utilisez des nombres de références sur des objects de base comme un vecteur de position.

Oui. c ++ règne suprême en performance / expression / compromis des ressources.

“Je cherche des données difficiles, pas de l’évangélisation”. Google est ton meilleur ami.

  1. obj-c nsssortingng est échangé avec c ++ par apple enginneers pour la performance. dans une ressource contenue dans des périphériques, seul c ++ le coupe en tant que langage MAINSTREAM oop. NSSsortingng ssortingngWithFormat est lente

  2. obj-c oop abstraction est décomposé en c-struct pour les performances, sinon un ordre MAGNITUDE plus lent que java! l’auteur est également au courant de la mise en cache des messages – mais pas du tout. Donc, modéliser beaucoup de petits joueurs / objects ennemis se fait dans oop avec c ++ ou bien beaucoup de structures avec un simple wrapper OOP avec obj-c. il peut y avoir un paradigme qui équivaut à la programmation procédurale + orientée object = obj-c. http://ejourneyman.wordpress.com/2008/04/23/writing-a-ray-tracer-for-cocoa-objective-c/