Tout le monde dit que je devrais rendre mon code modulaire, mais n'est-il pas moins efficace si j'utilise plus d'appels de méthode plutôt que moins, mais plus de méthodes? Quelle est la différence en Java, C ou C ++ d'ailleurs?
Je comprends qu'il est plus facile d'éditer, de lire et de comprendre, surtout en groupe. La perte de temps de calcul est-elle donc insignifiante par rapport aux avantages de l'ordre du code?
java
c++
c
efficiency
fatsokol
la source
la source
Réponses:
Oui, ce n'est pas pertinent.
Les ordinateurs sont des moteurs d'exécution infatigables, presque parfaits, fonctionnant à des vitesses totalement comparables à celles des cerveaux. Bien qu'il existe une quantité mesurable de temps qu'un appel de fonction ajoute au temps d'exécution d'un programme, ce n'est rien comparé au temps supplémentaire nécessaire au cerveau de la prochaine personne impliquée dans le code lorsqu'elle doit démêler la routine illisible pour même commencer à comprendre comment travailler avec. Vous pouvez essayer le calcul pour une blague - supposez que votre code ne doit être conservé qu'une seule fois , et cela n'ajoute qu'une demi-heure au temps nécessaire à quelqu'un pour accepter le code. Prenez la vitesse d'horloge de votre processeur et calculez: combien de fois le code devrait-il fonctionner pour même rêver de compenser cela?
En bref, avoir pitié du processeur est complètement, totalement erroné 99,99% du temps. Pour les rares cas restants, utilisez des profileurs. Ne présumez pas que vous pouvez repérer ces cas - vous ne pouvez pas.
la source
Ça dépend.
Dans le monde glacialement lent qu'est la programmation Web, où tout se passe à des vitesses humaines, une programmation lourde de méthode, où le coût de l'appel de méthode est comparable ou supérieur au coût du traitement effectué par la méthode, n'a probablement pas d'importance .
Dans le monde de la programmation de systèmes embarqués et des gestionnaires d'interruptions pour les interruptions à haut débit, cela a certainement de l'importance. Dans cet environnement, les modèles habituels «d'accès à la mémoire sont bon marché» et «le processeur est infiniment rapide» tombent en panne. J'ai vu ce qui se passe lorsqu'un programmeur orienté objet mainframe écrit son premier gestionnaire d'interruption à haut débit. Ce n'était pas joli.
Il y a plusieurs années, je faisais une coloration blob de connectivité à 8 voies non récursive sur des images FLIR en temps réel, sur ce qui était à l'époque un processeur décent. La première tentative a utilisé un appel de sous-programme, et la surcharge d'appel de sous-programme a mangé le processeur vivant. (4 appels PAR PIXEL x 64K pixels par image x 30 images par seconde = vous le comprenez). La deuxième tentative a changé le sous-programme en macro C, sans perte de lisibilité, et tout était rose.
Vous devez regarder DIFFICILEMENT ce que vous faites et l'environnement dans lequel vous le ferez.
la source
Tout d'abord: les programmes dans une langue supérieure sont destinés à être lus par des humains et non par des machines.
Donc , écrire les programmes afin que vous les comprenez. Ne pensez pas aux performances (si vous avez sérieusement des problèmes de performances, profilez votre application et améliorez les performances là où elles sont nécessaires).
Même s'il est vrai que l'appel d'une méthode ou d'une fonction prend un peu de temps, cela n'a pas d'importance. Aujourd'hui, les compilateurs devraient être capables de compiler votre code dans un langage machine efficace afin que le code généré soit efficace pour l'architecture cible. Utilisez les commutateurs d'optimisation de votre compilateur pour obtenir le code efficace.
la source
Généralement, lorsque vous auriez autrement une grande fonction et que vous la diviseriez en beaucoup de plus petites, ces plus petites seront alignées parce que le seul inconvénient de l'inline (répétant trop les mêmes instructions) n'est pas pertinent dans ce cas. Cela signifie que votre code agira comme si vous aviez écrit une grande fonction.
S'ils ne sont pas alignés pour une raison quelconque et que cela devient un problème de performances, vous devez alors envisager un alignement manuel. Toutes les applications ne sont pas des formulaires CRUD en réseau avec d'énormes latences intrinsèques.
la source
Il n'y a probablement aucun coût de calcul. Habituellement, les compilateurs / JIT depuis 10 à 20 ans environ traitent parfaitement la fonction d'inline. Pour le C / C ++, il est généralement limité aux fonctions «inlinables» (c'est-à-dire que la définition de la fonction est disponible pour le compilateur pendant la compilation - c'est-à-dire qu'elle se trouve dans l'en-tête du même fichier), mais les techniques actuelles de LTO le surmontent.
Si vous devez consacrer du temps à l'optimisation, cela dépend de la zone sur laquelle vous travaillez. Si vous traitez avec une application «normale» qui a passé la plupart du temps à attendre la saisie - vous ne devriez probablement pas vous soucier des optimisations à moins que l'application «ne semble» lente.
Même dans de tels cas, vous devez vous concentrer sur beaucoup de choses avant de faire de la micro-optimisation:
O(n)
àO(log n)
pourrait avoir un impact beaucoup plus important que tout ce que vous pourriez réaliser par micro-optimisation.List
quand vous en avez besoinHashSet
pour avoir desO(n)
recherches quand vous pourriez en avoirO(1)
.Même si vous décidez que vous devez effectuer une micro-optimisation (ce qui signifie pratiquement que votre logiciel est utilisé dans HPC, intégré ou simplement utilisé par un très grand nombre de personnes - sinon le coût supplémentaire de maintenance dépasse les coûts de temps de l'ordinateur) dont vous avez besoin pour identifier les hotspots (noyaux) que vous souhaitez accélérer. Mais alors vous devriez probablement:
Une dernière remarque. Habituellement, le seul problème que vous rencontrez avec les appels de méthode est les sauts indirects (méthodes virtuelles) qui n'étaient pas prédits par le prédicteur de branche (malheureusement, le saut indirect en est le cas difficile). Pourtant:
la source
Ma réponse ne développera probablement pas trop les réponses existantes, mais je pense que mes deux cents pourraient être utiles.
Tout d'abord; oui, pour la modularité, vous abandonnez généralement un certain niveau de temps d'exécution. Tout écrire dans le code assembleur vous donnera la meilleure vitesse. Cela dit...
Vous connaissez YouTube? Probablement soit le site à la bande passante la plus élevée qui existe, soit le deuxième derrière Netflix? Ils écrivent une grande partie de leur code en Python, qui est un langage hautement modulaire pas tout à fait conçu pour des performances de premier ordre.
Le problème est que, lorsque quelque chose ne va pas et que les utilisateurs se plaignent du chargement lent des vidéos, il n'y a pas beaucoup de scénarios où cette lenteur serait finalement attribuée à la vitesse d'exécution lente de Python. Cependant, la recompilation rapide de Python et sa capacité modulaire à essayer de nouvelles choses sans vérification de type permettront probablement aux ingénieurs de déboguer ce qui ne va pas assez rapidement ("Wow. Notre nouveau stagiaire a écrit une boucle qui fait une nouvelle sous-requête SQL pour CHAQUE résultat. ") ou (" Oh, Firefox a déprécié l'ancien format d'en-tête de mise en cache; et ils ont créé une bibliothèque Python pour configurer le nouveau facilement ")
En ce sens, même en termes de temps d'exécution, un langage modulaire peut être considéré comme plus rapide car une fois que vous aurez identifié vos goulots d'étranglement, il deviendra probablement plus facile de réorganiser votre code pour le faire fonctionner de la meilleure façon. Tant d'ingénieurs vous diront que les hits de performances élevées n'étaient pas là où ils pensaient qu'ils seraient (et en fait, les choses qu'ils ont DID optimisées n'étaient guère nécessaires; ou, ne fonctionnaient même pas comme ils l'attendaient!)
la source
Oui et non. Comme d'autres l'ont noté le programme pour la lisibilité d'abord, puis pour l'efficacité. Cependant, il existe des pratiques standard qui sont à la fois lisibles et efficaces. La plupart du code est exécuté assez rarement, et vous ne tirerez aucun avantage de l'optimisation de toute façon.
Java peut incorporer des appels de fonction plus petits, il n'y a donc pas de raison d'éviter d'écrire les fonctions. Les optimiseurs ont tendance à mieux fonctionner avec un code plus simple à lire. Il existe des études qui montrent que les raccourcis qui devraient théoriquement s'exécuter plus rapidement, prennent en fait plus de temps. Le compilateur JIT est susceptible de mieux fonctionner, le code est plus petit et les morceaux exécutés fréquemment peuvent être identifiés et optimisés. Je ne l'ai pas essayé mais je m'attendrais à une grande fonction qui est relativement rarement appelée pour ne pas être compilée.
Cela ne s'applique probablement pas à Java, mais une étude a révélé que les fonctions plus importantes fonctionnaient plus lentement en raison de la nécessité d'un modèle de référence de mémoire différent. C'était spécifique au matériel et à l'optimiseur. Pour les modules plus petits, des instructions fonctionnant dans une page mémoire ont été utilisées. Celles-ci étaient plus rapides et plus petites que les instructions requises lorsque la fonction ne cadrait pas avec une page.
Il y a des cas où il vaut la peine d'optimiser le code, mais généralement vous devez profiler le code pour déterminer où il se trouve. Je trouve que ce n'est souvent pas le code que j'attendais.
la source