web-dev-qa-db-fra.com

Pouvons-nous faire des déclarations générales sur les performances du code interprété par rapport au code compilé?

Je compare deux technologies afin de parvenir à une recommandation pour laquelle une devrait être utilisée par une entreprise. Le code de la technologie A est interprété tandis que le code de la technologie B est compilé en code machine. Dans ma comparaison, je déclare que la technologie B en général aurait de meilleures performances car elle n'a pas la surcharge supplémentaire du processus d'interprétation. Je déclare également qu'étant donné qu'un programme peut être écrit de plusieurs manières, il est toujours possible qu'un programme écrit en technologie A puisse surpasser un programme écrit en technologie B.

Lorsque j'ai soumis ce rapport pour examen, l'examinateur a déclaré que je n'avais pas expliqué pourquoi, en général, les frais généraux du processus d'interprétation seraient suffisamment importants pour que nous puissions conclure que les performances de la technologie B seraient meilleures.

Ma question est donc la suivante: pouvons-nous jamais dire quoi que ce soit sur les performances des technologies compilées/interprétées? Si nous pouvons dire que la compilation est généralement plus rapide qu'interprétée, comment pourrais-je convaincre le réviseur de mon argument?

60
EpicSam

Non.

En général, les performances d'une implémentation de langage dépendent principalement du montant d'argent, des ressources, de la main-d'œuvre, de la recherche, de l'ingénierie et du développement qui y sont dépensés.

Et en particulier, les performances d'un programme particulier dépendent principalement de la quantité de réflexion mise dans ses algorithmes.

Il existe des interprètes très rapides et certains compilateurs qui génèrent du code très lent.

Par exemple, l'une des raisons pour lesquelles Forth est toujours populaire, c'est parce que dans de nombreux cas, un programme Forth interprété est plus rapide que le programme C compilé équivalent, tandis qu'en même temps, le programme utilisateur écrit en Forth plus l'interprète Forth écrit en C est plus petit que le programme utilisateur écrit en C.

110
Jörg W Mittag

Les généralisations et les scénarios spécifiques sont littéralement opposés.

Vous semblez vous contredire. D'une part, vous voulez faire une déclaration générale sur les langages interprétés vs compilés. Mais d'un autre côté, vous voulez appliquer cette déclaration générale à un scénario concret impliquant la technologie A et la technologie B.

Une fois que vous avez appliqué quelque chose à un scénario concret, il n'est plus généralisé . Donc, même si vous pouvez faire valoir que les langages interprétés sont plus lents en général , vous ne faites toujours pas valoir votre point de vue. Votre critique ne se soucie pas des généralisations. Vous faites une analyse de deux technologies très spécifiques. C'est littéralement le contraire de la généralisation.

81
loneboat

En règle générale, un programme interprété est environ 2 à 10 fois plus lent que l'écriture du programme dans la langue hôte de l'interpréteur, les interprètes pour les langues plus dynamiques étant plus lents. Cela est dû au fait que le programme interprété doit effectuer tout le travail réel, mais qu'il a en outre des frais généraux d'interprétation.

Selon la structure de l'interprète, il peut y avoir des différences très importantes. Il existe deux écoles contradictoires de conception d'interprètes: l'une dit que les opcodes devraient être aussi petits que possible afin qu'ils puissent être optimisés plus facilement, l'autre dit que les opcodes devraient être aussi grands que possible afin que nous fassions plus de travail au sein de l'interpréteur. Lorsque la structure de votre programme correspond à la philosophie de l'interprète, les frais généraux deviennent négligeables.

Par exemple. Perl est un langage interprété orienté vers la manipulation de texte. Un programme Perl idiomatique faisant de la manipulation de texte ne sera pas beaucoup plus lent qu'un programme C, et peut même surpasser le programme C dans certains cas (possible parce que Perl utilise une représentation de chaîne différente et dispose de diverses optimisations liées au texte et aux E/S intégrées). Cependant, le calcul des nombres en Perl va être insupportablement lent. Un incrément ++x est une instruction d'assemblage unique, mais implique plusieurs traversées de pointeurs et branches pour l'interpréteur Perl. J'ai récemment porté un script Perl lié au CPU en C++, et j'ai obtenu une accélération de 7x à 20x, selon le niveau d'optimisation du compilateur.

Il est important de parler d'optimisations ici, car un interpréteur optimisé et raffiné peut raisonnablement surpasser un compilateur naïf non optimisant. La création d'un compilateur d'optimisation étant difficile et nécessitant beaucoup d'efforts, il est peu probable que votre "technologie B" ait ce niveau de maturité.

(Remarque: le site Computer Language Benchmarks Game a une structure déroutante, mais une fois que vous atteignez le tableau des horaires pour un problème, vous remarquerez que les performances de différentes langues sont partout - souvent, là n'est pas une limite de performance claire entre les solutions compilées et interprétées. La partie la plus importante du site n'est pas les résultats de référence, mais les discussions sur la difficulté des références significatives.)

Lors du choix d'une technologie, les performances d'un runtime de langue en elles-mêmes sont complètement hors de propos. Il est plus probable qu'il soit important que la technologie réponde à certaines contraintes de base (notre budget est de x $, nous devons être en mesure de livrer avant aaaa-mm-jj, nous devons satisfaire diverses exigences non fonctionnelles), et coût total de possession (prise en compte de la productivité des développeurs, coûts matériels, coûts d'opportunité commerciale, risque de bugs et contraintes technologiques inattendues, coûts de maintenance, coûts de formation et de recrutement,…). Par exemple. dans une industrie où le délai de mise sur le marché est le facteur le plus important, la technologie avec la meilleure productivité de développeur serait la meilleure solution. Pour une grande organisation, la maintenabilité et les coûts à long terme peuvent être plus intéressants.

37
amon

Vous pouvez absolument dire quelque chose sur les performances des technologies compilées/interprétées. Mais d'abord, vous devez définir la "performance". Si vous construisez un système embarqué simple sur le plan informatique, les "performances" pencheront probablement du côté de l'utilisation de la mémoire. Alors qu'un système complexe sur le plan des calculs et fonctionnant sur des ensembles de données volumineux se retrouverait à définir des "performances" dans le nombre de calculs par unité de temps, car la surcharge mémoire de JVM ou .NET serait négligeable.

Une fois que vous avez décidé de ce que sont les "performances", vous pouvez dire quelque chose comme "nous aurons 50 milliards d'objets en mémoire à tout moment et la technologie interprétée ajoute 8 octets supplémentaires à chaque objet pour la gestion interne, ce qui équivaut à une surcharge de mémoire de 400 Go. par rapport à techB qui n'ajoute pas ces données "

18
jhbh

Il s'agit d'une question technique et vous avez déjà obtenu de nombreuses bonnes réponses techniques, mais je voudrais souligner un aspect légèrement différent de votre situation: le fait que vous ne pouvez pas simplement baser une décision comme "technologie A ou technologie B" purement pour des raisons techniques et/ou de performance.

Les aspects techniques de quelque chose comme ça ne sont qu'une petite partie de la décision entre A et B.Il y a des dizaines d'autres facteurs à garder à l'esprit:

  • cela implique-t-il des frais de licence? Par exemple: vous devez payer (un montant substantiel) pour utiliser un cluster de machines SQL Server par rapport à l'utilisation d'un cluster de machines PostgreSQL.
  • ai-je des employés qui connaissent cette technologie (pile) et son écosystème? Si oui, sont-ils disponibles? Si non, puis-je en embaucher? Combien cela va-t-il me coûter? Ou dois-je former ceux qui existent déjà? Combien cela me coûtera-t-il?
  • que veut le client? Cela peut être un problème la plupart du temps.
  • la technologie que je recommande est-elle prête à être utilisée en production? Ou est-ce juste un battage médiatique actuel qui s'éteindra peut-être? (par exemple, pensez à Node.js lors de sa première sortie)
  • la technologie que je recommande s'intègre-t-elle bien à l'architecture existante ou à l'architecture à laquelle je pensais? Ou dois-je dépenser beaucoup d'argent en les faisant fonctionner ensemble de manière transparente?
  • et bien d'autres aspects qui dépendent de votre situation spécifique.

Comme vous pouvez le voir, il y a UNE TONNE de choses à considérer lorsque vous prenez une telle décision.

Je sais que cela ne répond pas spécifiquement à votre question, mais je pense que cela apporte une vision plus globale de votre situation et des détails d'une telle décision.

12
Radu Murzea

Évaluation partielle est un cadre conceptuel pertinent pour relier les interprètes et les compilateurs.

Pouvons-nous faire des déclarations générales sur les performances du code interprété par rapport au code compilé?

Les langages de programmation sont des spécifications (écrites dans certains rapports, telles que R5RS ou n157 ). Ce ne sont pas des logiciels , donc il n'est même pas logique de parler de performances . Mais certains langages de programmation peuvent avoir plusieurs implémentations, y compris interprètes et compilateurs .

Même dans les langages compilés traditionnellement (c'est-à-dire les langages dont les implémentations sont souvent des compilateurs) comme C, certaines parties sont souvent interprétées. Par exemple, la chaîne de contrôle de format de printf (définie dans la norme C) est souvent "interprétée" (par le - bibliothèque standard C , qui a une fonction printf utilisant des techniques d'arguments variables) mais certaines les compilateurs (y compris GCC ) peuvent -in limités cas spécifiques - pour l'optimiser et le "compiler" en appels de niveau inférieur.

Et certaines implémentations, même au sein des "interprètes", utilisent des techniques compilation JIT (donc générez du code machine à runtime ). Un bon exemple est luajit . D'autres implémentations (par exemple Python, Ocaml, Java, Parrot, Lua) traduisent le code source en bytecode qui est ensuite interprété.

SBCL est un "compilateur" LISP commun qui traduit dynamiquement chaque REPL interaction (et appels à eval etc ...) dans le code machine. Vous pensez donc que c'est un interprète. La plupart des implémentations JavaScript dans les navigateurs (par exemple v8 ) utilisent des techniques de compilation JIT.

En d'autres termes, la différence entre les interprètes et les compilateurs est très floue (en fait, il y a un continuum entre les deux), et pratiquement parlant, la plupart des implémentations de langage de programmation ont souvent à la fois un interprète et une facette du compilateur (au moins en octets de code).

Une implémentation peut être rapide ou lente indépendamment de l'utilisation de la plupart des techniques de type "compilateur" ou "interprète".

Certains traits de langage favorisent une approche d'interprétation (et ne peuvent être compilés efficacement qu'à travers l'ensemble du programme analyse).

Pour certains types de problèmes , la conception du logiciel avec certaines approches métaprogrammation vaut la peine et donne des accélérations importantes. Vous pourriez imaginer qu'avec une entrée spécifique, votre programme dynamiquement génère du code spécialisé pour le traiter. C'est même possible avec C ou C++ (soit en utilisant une bibliothèque JIT, soit en générant du code C, en le compilant comme un plugin qui se charge dynamiquement).

Voir aussi this related question sur Python, et that

10

Pour le code comme A = A + B, Cela peut se compiler en une ou deux instructions machine, chacune prenant un certain nombre de cycles. Aucun interprète ne peut faire la même chose dans ce nombre de cycles pour une raison simple.

L'interpréteur exécute également un jeu d'instructions qui lui est propre (appelez-les octets-codes, p-codes, langage intermédiaire, peu importe). Chaque fois qu'il voit un octet-code comme ADD, il doit le chercher et se ramifier au code qui fait l'addition.

Le prochain moment où il le voit, il doit répéter cette recherche, sauf si il a un moyen de se souvenir de la recherche précédente. S'il a un moyen de se souvenir de la recherche précédente, ce n'est plus ce que nous appelons un "interprète", mais plutôt un compilateur juste à temps, ou JITter.

D'autre part...

Pour un code comme callSomeFunction( ... some args ...), combien de cycles sont passés entre la saisie de ce code et sa sortie? Tout dépend de ce qui se passe à l'intérieur de callSomeFunction. Ce pourrait être quelques-uns, et ce pourrait être des milliards, même si callSomeFunction est lui-même compilé. Si c'est beaucoup, il est inutile de débattre du coût d'interprétation de cette ligne de code - l'argent est ailleurs.

N'oubliez pas que les langages interprétés ont une valeur qui leur est propre, par exemple, pas besoin de les compiler. (La "compilation" de la syntaxe de surface en codes octets prend un temps trivial. Prenez R ou MATLAB, par exemple.)

De plus, une flexibilité est nécessaire pour des niveaux de programmation intelligents. Dans la société Minsky Society of Mind , chapitre 6.4 [~ # ~] b [~ # ~] - Cerveau, il y a des programmes A qui traitent du monde, et il y a des programmes B qui traitent des programmes A, et il peut y avoir d'autres niveaux. Les programmes qui écrivent et gèrent d'autres programmes peuvent être plus facilement exécutés dans les systèmes d'interprétation.

Dans LISP, vous pouvez écrire (+ A B) Pour ajouter A et B, mais une fois qu'il est écrit, vous n'avez que le choix de l'exécuter ou non. Vous pouvez également écrire (eval (list '+ 'A 'B)) Qui construit le programme puis l'exécute. Cela pourrait construire quelque chose de différent.

Le sujet du programme est un autre programme . Ceci est plus facile à écrire dans un langage interprété (bien que, comme le souligne Jörg, les nouvelles versions de LISP, alors qu'elles ont eval, compilent à la volée, donc elles n'ont pas la pénalité de vitesse d'interprétation ).

7
Mike Dunlavey

Votre hypothèse est bien fondée, bien que ce soit une hypothèse.

Je ne vais pas passer en revue les raisons pour lesquelles le code compilé devrait être plus rapide que le code interprété: si vous savez comment les ordinateurs fonctionnent, cela sera évident. La différence peut être des ordres de grandeur pour certains types de problèmes. Si votre critique conteste sérieusement ce cas général, il ne sait pas de quoi il parle.

Cependant, ils peuvent avoir un point à savoir si la différence est significative dans le type d'application que vous développez. S'il s'agit principalement d'E/S ou d'appels de bibliothèques compilées et qu'il n'a pas beaucoup de calcul, le surcoût du processus d'interprétation peut en effet être insignifiant.

Mais le point de mon message est le suivant: en tant que I.T. expert, vous serez souvent appelé à prendre des décisions instantanées sur la base d'une connaissance générale du fonctionnement des choses. Faire un test spécifique pourrait vous donner une réponse plus précise, mais cela coûtera beaucoup plus et ne vous y mènera pas en premier.

Mais de temps en temps, on se fait prendre. Ça m'est arrivé. Vous faites une bonne hypothèse et vous vous rendez compte que vous n'avez pas pris en compte la stupidité du monde.

Mais je ne peux pas expliquer aussi bien que mon dessin animé Dilbert préféré de tous les temps. Rien ne montre mieux que cela les dangers d'être un cul intelligent.

alt text

TL; DR: vous devriez avoir raison, mais vérifiez le monde réel au cas où.

5
rghome

En quelque sorte, cela dépend, mais en règle générale, l'environnement compilé - que ce soit via JIT ou compilé statiquement - sera plus rapide pour de nombreuses tâches à forte intensité de calcul - en supposant pour simplifier le même langage.

Une partie de la raison est que les langages interprétés doivent avoir une boucle interpréteur - boucle qui lit une instruction, sélectionne l'action appropriée à entreprendre et l'exécute. Dans le meilleur des cas, comme interpréter Python ou Java bytecode (as old JVM did ), il a un surcoût de quelques instructions et a fait des ravages avec le prédicteur de branche - sans le dernier, vous pouvez vous attendre à d'énormes pénalités en raison de mauvaises prédictions. Même un JIT très stupide devrait accélérer considérablement.

Cela dit, le langage interprété peut tricher. Par exemple, Matlab a des routines optimisées pour la multiplication matricielle et avec peu de changements, vous pouvez faire fonctionner le code sur GPU (avertissement: je travaille pour nVidia - toute opinion exprimée ici est la mienne et ne représente pas l'opinion de mon employeur). De cette façon, vous pouvez écrire du code de niveau supérieur court et puissant sans vous soucier des détails - quelqu'un s'en est occupé et a consacré du temps et des ressources à l'optimiser dans un langage de bas niveau. Il n'y a rien d'héritier et cela n'empêche pas, par exemple, Matlab de JIT le code mais souvent il n'y a aucune raison car les frais généraux d'appeler la routine de haut niveau sont minimes par rapport au temps passé dans les bas niveau.

TL; DR - les programmes compilés ont d'énormes avantages en termes de performances par rapport aux programmes interprétés (pour la comparaison pommes-pommes, voir PyPy Speed ). Cependant, la vitesse de l'exécutable n'est qu'une partie du problème et elle peut ne pas contribuer beaucoup à la vitesse globale (si le temps est principalement passé dans les bibliothèques). La mise en œuvre est également importante.

5
Maciej Piechotka

À moins que vous n'utilisiez quelque chose d'un peu exotique, votre problème ne concernera pas les performances d'un langage interprété A et d'un langage compilé B.

Parce que si vous/votre équipe connaissez A et non B et écrivez donc un meilleur code en A qu'en B, vous pouvez finir par avoir de bien meilleures performances en A qu'en B. Si vous avez des gens expérimentés dans une langue et que la langue/les bibliothèques peuvent faire le travail dont vous avez besoin, respectez-le.

Voici un lien sur l'expression régulière dans différentes langues; vous verrez que les expressions régulières sont mieux implémentées dans certaines langues, même si elles sont compilées ou non: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna

3
Walfrat

Je pense que ce n'est tout simplement pas une bonne idée de parler des performances de deux technologies simplement parce que l'une est compilée et l'autre interprétée. Comme indiqué dans d'autres réponses, cela peut dépendre du domaine d'application (certaines langues peuvent être optimisées pour effectuer certaines opérations très rapidement et faire d'autres choses plus lentement) ainsi que de l'expérience des personnes qui sont sur le point d'utiliser cette technologie.

Je ne pense pas qu'il soit raisonnable de s'attendre à ce que vous obteniez une amélioration des performances si vous prenez d'excellents codeurs de langage interprétés et leur donnez une technologie qu'ils ne connaissent pas - peut-être qu'en théorie, cette dernière PEUT entraîner de meilleures performances, mais en réalité, sans les compétences et l'expérience nécessaires, vous n'utiliserez pas toutes les opportunités d'optimisation.

De l'un des employés bien connus de la société Silicon Valley, j'ai également entendu dire qu'ils préfèrent le langage plus simple à utiliser car il est plus coûteux et difficile de payer certains développeurs qualifiés pour maintenir un code compliqué, mais hautement optimisé, que juste pour acheter plus de plate-forme afin de faire face à la mise en œuvre moins efficace, de sorte que devrait également être pris en compte lors du choix de la technologie.

1
KjMag

Une fois, j'ai dû faire une déclaration similaire pour justifier une grande décision.

Tout d'abord, ils ne veulent peut-être pas croire un humble ingénieur, j'ai donc trouvé des tests de référence comparables et les ai cités. Il y en a beaucoup, par des gens comme Microsoft ou des universités renommées. Et ils diront des trucs comme: La méthode A est entre 3 et 10 fois plus rapide que la méthode B, selon les variables X et Y.

Deuxièmement, vous voudrez peut-être exécuter votre propre benchmark, peut-être en utilisant un morceau représentatif du code en question, ou quelque chose de similaire que vous avez déjà. Exécutez-le 1000 fois pendant la nuit pour qu'il y ait vraiment une différence mesurable.

À ce stade, la différence (ou son absence) entre A et B doit être si claire que vous n'avez qu'à la présenter. Formatez donc clairement les résultats, avec des diagrammes si possible, en indiquant toutes les hypothèses et en définissant toutes les données utilisées.

0
RedSonja

Je dirais que tout langage dynamique a un avantage sur les langages compilés statiquement: "Optimisations d'exécution"

C'est l'une des raisons pour lesquelles Java peut être plus rapide que C++

Oui, chargement une langue typée dynamiquement aura toujours le coût de la traduction et sera désavantagée. Mais une fois qu'il est en cours d'exécution, l'interpréteur peut profiler et améliorer les chemins de code fréquents avec des informations d'exécution que les langages statiques n'auront jamais

REMARQUE: Eh bien, Java est un langage interprété, pas un langage dynamique. Mais c'est un excellent exemple de ce que vous pouvez accélérer avec les informations d'exécution

0
SystematicFrank