En écoutant le podcast StackOverflow, le jab continue de dire que les "vrais programmeurs" écrivent en C, et que C est tellement plus rapide parce qu'il est "proche de la machine". Laissant l'ancienne affirmation pour un autre poste, quelle est la particularité de C qui lui permet d'être plus rapide que les autres langues? Ou en d'autres termes: qu'est-ce qui empêche les autres langages de pouvoir compiler en binaire qui s'exécute tout aussi vite que C?
c
performance
Mike C.
la source
la source
Réponses:
Il n'y a pas grand-chose de spécial à propos de C. C'est l'une des raisons pour lesquelles c'est rapide.
Langages plus récents qui prennent en charge la récupération de place , la frappe dynamique et d'autres fonctionnalités qui facilitent l'écriture de programmes par le programmeur.
Le hic, c'est qu'il y a des frais supplémentaires de traitement qui dégraderont les performances de l'application. C n'a rien de tout cela, ce qui signifie qu'il n'y a pas de surcharge, mais cela signifie que le programmeur doit être en mesure d'allouer de la mémoire et de les libérer pour éviter les fuites de mémoire , et doit gérer le typage statique des variables.
Cela dit, de nombreux langages et plates-formes, tels que Java (avec sa machine virtuelle Java ) et .NET (avec son Common Language Runtime) ont amélioré les performances au fil des ans grâce à des avantages tels que la compilation juste à temps qui produit du code machine natif à partir de bytecode pour obtenir de meilleures performances.
la source
Il y a un compromis que les concepteurs C ont fait. C'est-à-dire qu'ils ont décidé de mettre la vitesse au-dessus de la sécurité. C ne sera pas
Lorsque vous indexez dans un tableau, en Java, il faut un appel de méthode dans la machine virtuelle, une vérification des liens et d'autres vérifications d'intégrité. C'est valable et tout à fait correct , car cela ajoute de la sécurité là où c'est dû. Mais en C, même des choses assez banales ne sont pas mises en sécurité. Par exemple, C ne nécessite pas memcpy pour vérifier si les régions à copier se chevauchent. Il n'est pas conçu comme un langage pour programmer une application de grande entreprise.
Mais ces décisions de conception sont pas des bugs dans le langage C . Ils sont de par leur conception, car ils permettent aux compilateurs et aux rédacteurs de bibliothèques de tirer le maximum de performances de l'ordinateur. Voici l'esprit de C comment le document de justification C l' explique:
la source
Si vous passez un mois à construire quelque chose en C qui s'exécute en 0,05 seconde, et que je passe une journée à écrire la même chose en Java, et cela s'exécute en 0,10 seconde, alors C est-il vraiment plus rapide?
Mais pour répondre à votre question, un code C bien écrit s'exécutera généralement plus rapidement que du code bien écrit dans d'autres langues car une partie de l'écriture "bien" du code C comprend la réalisation d'optimisations manuelles à un niveau proche de la machine.
Bien que les compilateurs soient en effet très intelligents, ils ne sont pas encore capables de créer de manière créative du code qui rivalise avec les algorithmes massés à la main (en supposant que les "mains" appartiennent à un bon programmeur C).
Éditer:
Beaucoup de commentaires vont dans le sens de «j'écris en C et je ne pense pas aux optimisations».
Mais pour prendre un exemple spécifique de ce post :
En Delphi, je pourrais écrire ceci:
et en CI écrivez ceci:
Mais combien d'optimisations y a-t-il dans la version C? Nous prenons beaucoup de décisions sur l'implémentation auxquelles je ne pense pas dans la version Delphi. Comment une chaîne est-elle implémentée? Dans Delphi, je ne le vois pas. En C, j'ai décidé que ce sera un pointeur vers un tableau d'entiers ASCII, que nous appelons des caractères. En C, nous testons l'existence des personnages un par un. En Delphi, j'utilise Pos.
Et ce n'est qu'un petit exemple. Dans un grand programme, un programmeur C doit prendre ce type de décisions de bas niveau avec quelques lignes de code. Il s'ajoute à un exécutable fabriqué à la main et optimisé à la main.
la source
Je ne l'ai pas déjà, donc je vais le dire: C a tendance à être plus rapide parce que presque tout est écrit ailleurs dans C .
Java est construit sur C, Python est construit sur C (ou Java, ou .NET, etc.), Perl est, etc. Le système d'exploitation est écrit en C, les machines virtuelles sont écrites en C, les compilateurs sont écrits en C, les interprètes sont écrits en C. Certaines choses sont toujours écrites en langage assembleur, ce qui tend à être encore plus rapide. De plus en plus de choses sont écrites dans quelque chose d'autre, qui est lui-même écrit en C.
Chaque instruction que vous écrivez dans d'autres langages (et non Assembly) est généralement implémentée sous la forme de plusieurs instructions en C, qui sont compilées en code machine natif. Étant donné que ces autres langages ont tendance à exister afin d'obtenir un niveau d'abstraction plus élevé que C, ces instructions supplémentaires requises en C ont tendance à se concentrer sur l'ajout de sécurité, l'ajout de complexité et la gestion des erreurs. Ce sont souvent de bonnes choses, mais elles ont un coût , et ses noms sont vitesse et taille .
Personnellement, j'ai écrit dans des dizaines de langues couvrant la plupart du spectre disponible, et j'ai personnellement recherché la magie à laquelle vous faites allusion:
Après quelques années de recherche, ma réponse est Python (sur C). Vous voudrez peut-être y jeter un œil. Soit dit en passant, vous pouvez également accéder à Assembly depuis Python (avec une aide mineure d'une bibliothèque spéciale).
D'un autre côté, un mauvais code peut être écrit dans n'importe quelle langue . Par conséquent, le code C (ou Assembly) n'est pas automatiquement plus rapide. De même, certaines astuces d'optimisation peuvent rapprocher des portions de code de langage de niveau supérieur du niveau de performance du C. brut, mais pour la plupart des applications, votre programme passe la plupart de son temps à attendre des personnes ou du matériel, de sorte que la différence n'a pas vraiment d'importance.
Prendre plaisir.
la source
Il y a beaucoup de questions là-dedans - surtout celles auxquelles je ne suis pas qualifié pour répondre. Mais pour ce dernier:
En un mot, l'abstraction.
C n'est qu'un ou deux niveaux d'abstraction loin du langage machine. Java et les langages .Net sont à au moins 3 niveaux d'abstraction loin de l'assembleur. Je ne suis pas sûr de Python et Ruby.
En règle générale, plus il y a de jouets de programmation (types de données complexes, etc.), plus vous vous éloignez du langage machine et plus vous devez faire de traduction.
Je suis ici et là, mais c'est l'essentiel.
Mise à jour ------- Il y a de bons commentaires sur ce post avec plus de détails.
la source
Ce n'est pas tant que C est rapide que le modèle de coût de C est transparent . Si un programme C est lent, il est lent d'une manière évidente: en exécutant beaucoup d'instructions. Par rapport au coût des opérations en C, les opérations de haut niveau sur les objets (notamment la réflexion) ou les chaînes peuvent avoir des coûts qui ne sont pas évidents.
Deux langages qui se compilent généralement en binaires aussi rapides que C sont le ML standard (à l'aide du compilateur MLton ) et l' Objective Caml . Si vous consultez le jeu de benchmarks, vous constaterez que pour certains benchmarks, comme les arbres binaires, la version OCaml est plus rapide que C. (Je n'ai trouvé aucune entrée MLton.) Mais ne prenez pas la fusillade trop au sérieux; c'est, comme il est dit, un jeu, les résultats reflètent souvent l'effort que les gens ont mis pour régler le code.
la source
C n'est pas toujours plus rapide.
C est plus lent que, par exemple Modern Fortran.
C est souvent plus lent que Java pour certaines choses. (Surtout après que le compilateur JIT a essayé votre code)
C laisse l'alias du pointeur se produire, ce qui signifie que de bonnes optimisations ne sont pas possibles. En particulier, lorsque vous avez plusieurs unités d'exécution, cela entraîne des blocages de récupération de données. Ow.
L'hypothèse que l'arithmétique du pointeur fonctionne vraiment ralentit les performances gonflées sur certaines familles de processeurs (PIC en particulier!). Il utilisé pour aspirer le gros sur x86 segmenté.
Fondamentalement, lorsque vous obtenez une unité vectorielle ou un compilateur de parallélisation, C pue et le Fortran moderne s'exécute plus rapidement.
Les astuces du programmeur C comme le thunking (modification de l'exécutable à la volée) provoquent des blocages de prélecture du processeur.
Vous obtenez la dérive?
Et notre bon ami, le x86, exécute un jeu d'instructions qui, de nos jours, n'a que peu de rapport avec l'architecture réelle du CPU. Registres fantômes, optimiseurs de magasin de charge, tous dans le CPU. C est donc proche du métal virtuel. Le vrai métal, Intel ne vous laisse pas voir. (Historiquement, les processeurs VLIW étaient un peu difficiles, peut-être que ce n'est pas si mal.)
Si vous programmez en C sur un DSP haute performance (peut-être un TI DSP?), Le compilateur doit faire des choses délicates pour dérouler le C sur les multiples unités d'exécution parallèles. Donc, dans ce cas, C n'est pas proche du métal, mais il est proche du compilateur, qui fera toute l'optimisation du programme. Bizarre.
Et enfin, certains CPU (www.ajile.com) exécutent des bytecodes Java dans le matériel. C serait un PITA à utiliser sur ce CPU.
la source
Rien. Les langages modernes comme Java ou .NET sont plus axés sur la productivité du programmeur que sur les performances. Le matériel est bon marché de nos jours. La compilation en représentation intermédiaire offre également de nombreux avantages tels que la sécurité, la portabilité, etc.
la source
Les principaux facteurs sont qu'il s'agit d'un langage de type statique et qui est compilé en code machine. De plus, comme c'est un langage de bas niveau, il ne fait généralement rien que vous ne lui dites pas.
Ce sont d'autres facteurs qui me viennent à l'esprit.
Cependant, la plupart des langages de type statique peuvent être compilés aussi rapidement ou plus rapidement que C, surtout s'ils peuvent faire des suppositions que C ne peut pas en raison de l'alias de pointeur, etc.
la source
Je suppose que vous avez oublié que le langage d'assemblage est aussi un langage :)
Mais sérieusement, les programmes C ne sont plus rapides que lorsque le programmeur sait ce qu'il fait. Vous pouvez facilement écrire un programme C qui s'exécute plus lentement que les programmes écrits dans d'autres langues qui font le même travail.
La raison pour laquelle C est plus rapide est qu'il est conçu de cette façon. Il vous permet de faire beaucoup de choses de "niveau inférieur" qui aident le compilateur à optimiser le code. Ou, dirons-nous, vous le programmeur êtes responsable de l'optimisation du code. Mais c'est souvent assez délicat et sujet aux erreurs.
D'autres langues, comme d'autres déjà mentionnées, se concentrent davantage sur la productivité du programmeur. Il est communément admis que le temps programmeur est beaucoup plus cher que le temps machine (même dans l'ancien temps). Il est donc très logique de minimiser le temps que les programmeurs passent à écrire et déboguer des programmes au lieu de la durée d'exécution des programmes. Pour ce faire, vous sacrifierez un peu ce que vous pouvez faire pour accélérer le programme car beaucoup de choses sont automatisées.
la source
Pour la plupart, chaque instruction C correspond à très peu d'instructions d'assembleur. Vous écrivez essentiellement du code machine de niveau supérieur, vous avez donc le contrôle de presque tout ce que fait le processeur. De nombreux autres langages compilés, tels que C ++, ont beaucoup d'instructions simples qui peuvent se transformer en beaucoup plus de code que vous ne le pensez (fonctions virtuelles, constructeurs de copie, etc.) Et les langages interprétés comme Java ou Ruby ont une autre couche de instructions que vous ne voyez jamais - la machine virtuelle ou l'interpréteur.
la source
Je sais que beaucoup de gens l'ont dit de manière longue, mais:
la source
C ++ est plus rapide en moyenne (comme c'était initialement, en grande partie un surensemble de C, bien qu'il y ait quelques différences). Cependant, pour des benchmarks spécifiques, il existe souvent un autre langage qui est plus rapide.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/
fannjuch-redux
a été le plus rapide à Scalan-body
etfasta
étaient plus rapides à Ada.spectral-norm
était le plus rapide à Fortran.reverse-complement
,mandelbrot
Etpidigits
ont été le plus rapide ATS.regex-dna
était le plus rapide en JavaScript.chameneou-redux
était le plus rapide est Java 7.thread-ring
a été le plus rapide à Haskell.Les autres benchmarks étaient les plus rapides en C ou C ++.
la source
extern "C"
n'a rien à voir avec C ++ étant un sur - ensemble de C.system("bash script.sh");
marche pour n'importe quel script bash, et donc C est un sur-ensemble de bash.extern "C"
fournit la liaison C en C ++ en raison du changement de nom. Alors que l'appel de X en tant que sur-ensemble de Y signifie que tout ce qui peut être fait en Y peut également l'être en X, ce qui n'est pas le cas de C ++. Il existe plusieurs constructions de langage valides en C mais pas en C ++.bash
un programme de ligne de commande disponible. S'il le faisait et incluait la version / spécification de bash qui devait être prise en charge, je considérerais que c'est un surensemble.struct foo { int: this; }; typedef float foo;
Beaucoup de ces réponses donnent des raisons valables pour lesquelles C est, ou n'est pas, plus rapide (en général ou dans des scénarios spécifiques). Il est indéniable que:
Malgré tout cela, il y a autre chose que j'ai remarqué qui, je pense, affecte la performance comparative de C par rapport à de nombreux autres langages plus que tout autre facteur. En être témoin:
D'autres langages facilitent souvent l'écriture de code qui s'exécute plus lentement. Souvent, il est même encouragé par les philosophies de conception de la langue. Corollaire: un programmeur C est plus susceptible d'écrire du code qui n'effectue pas d'opérations inutiles.
Par exemple, considérons un simple programme Windows dans lequel une seule fenêtre principale est créée. La version AC remplirait une
WNDCLASS[EX]
structure qui serait passée àRegisterClass[Ex]
, puis appelerCreateWindow[Ex]
et entrer une boucle de message. Le code très simplifié et abrégé suit:Un programme équivalent en C # pourrait être une seule ligne de code:
Cette ligne de code fournit toutes les fonctionnalités de près de 20 lignes de code C et ajoute certaines choses que nous avons omises, telles que la vérification des erreurs. La bibliothèque plus riche et plus complète (par rapport à celles utilisées dans un projet C typique) a fait beaucoup de travail pour nous, nous laissant ainsi le temps d'écrire de nombreux extraits de code qui nous paraissent courts mais qui impliquent de nombreuses étapes en arrière-plan.
Mais une bibliothèque riche permettant un ballonnement de code facile et rapide n'est pas vraiment mon point. Mon point est plus apparent lorsque vous commencez à examiner ce qui se passe réellement lorsque notre petit one-liner s'exécute. Pour le plaisir, parfois, activez l'accès aux sources .NET dans Visual Studio 2008 ou supérieur, et entrez dans le simple one-linef ci-dessus. L'un des petits joyaux amusants que vous rencontrerez est ce commentaire dans le getter pour
Control.CreateParams
:Dix fois . Les informations à peu près équivalentes à la somme de ce qui est stocké dans une
WNDCLASSEX
structure et de ce qui est transmisCreateWindowEx
sont extraites de laControl
classe dix fois avant d' être stockées dans uneWNDCLASSEX
structure et transmises àRegisterClassEx
etCreateWindowEx
.Dans l'ensemble, le nombre d'instructions exécutées pour effectuer cette tâche très basique est de 2 à 3 ordres de grandeur de plus en C # qu'en C. Une partie de cela est due à l'utilisation d'une bibliothèque riche en fonctionnalités, qui est nécessairement généralisée, par rapport à notre simple code C qui fait exactement ce dont nous avons besoin et rien de plus. Mais cela est dû en partie au fait que la nature modulaire et orientée objet du framework .NET se prête à de nombreuses répétitions d'exécution qui sont souvent évitées par une approche procédurale.
Je n'essaye pas de choisir C # ou le framework .NET. Je ne dis pas non plus que la modularisation, la généralisation, les fonctionnalités de bibliothèque / langage, la POO, etc. sont de mauvaises choses . J'ai utilisé pour faire la plupart de mon développement en C, plus tard en C ++, et plus récemment en C #. De même, avant C, j'utilisais principalement l'assemblage. Et à chaque étape «plus haut» de ma langue, j'écris des programmes meilleurs, plus faciles à maintenir et plus robustes en moins de temps. Ils ont cependant tendance à s'exécuter un peu plus lentement.
la source
Je ne pense pas que quiconque ait mentionné le fait que beaucoup plus d'efforts ont été consacrés aux compilateurs C que tout autre compilateur, à l'exception peut-être de Java.
C est extrêmement optimisable pour de nombreuses raisons déjà mentionnées - plus que presque tout autre langage. Donc, si la même quantité d'efforts est mise dans d'autres compilateurs de langage, C sera probablement toujours en tête.
Je pense qu'il y a au moins un langage candidat qui, avec effort, pourrait être optimisé mieux que C et donc nous pourrions voir des implémentations qui produisent des binaires plus rapides. Je pense au mars numérique D parce que le créateur a pris soin de construire un langage qui pourrait potentiellement être mieux optimisé que C. Il peut y avoir d'autres langages qui ont cette possibilité. Cependant, je ne peux pas imaginer que n'importe quel langage aura des compilateurs plus de quelques pour cent plus rapides que les meilleurs compilateurs C. J'adorerais me tromper.
Je pense que le vrai "fruit à faible pendaison" sera dans des langages conçus pour être FACILES à optimiser pour les humains. Un programmeur compétent peut accélérer n'importe quel langage - mais parfois vous devez faire des choses ridicules ou utiliser des constructions non naturelles pour y arriver. Bien que cela prenne toujours des efforts, un bon langage devrait produire un code relativement rapide sans avoir à se soucier exactement de la façon dont le programme est écrit.
Il est également important (au moins pour moi) que le pire des cas ait tendance à être rapide. Il existe de nombreuses "preuves" sur le Web que Java est aussi rapide ou plus rapide que C, mais cela est basé sur des exemples de sélection de cerises. Je ne suis pas un grand fan de C, mais je sais que TOUT ce que j'écris en C va bien fonctionner. Avec Java, il fonctionnera «probablement» à moins de 15% de la vitesse, généralement à moins de 25%, mais dans certains cas, il peut être bien pire. Tous les cas où il est tout aussi rapide ou dans quelques pour cent sont généralement dus au fait que la plupart du temps est passé dans le code de bibliothèque qui est fortement optimisé C de toute façon.
la source
C'est en fait un peu un mensonge perpétué. S'il est vrai que les programmes C sont souvent plus rapides, ce n'est pas toujours le cas, surtout si le programmeur C n'est pas très bon dans ce domaine.
Un gros trou flagrant que les gens ont tendance à oublier, c'est quand le programme doit bloquer pour une sorte d'E / S, comme l'entrée utilisateur dans n'importe quel programme GUI. Dans ces cas, peu importe la langue que vous utilisez, car vous êtes limité par la vitesse à laquelle les données peuvent arriver plutôt que par la vitesse à laquelle vous pouvez les traiter. Dans ce cas, peu importe si vous utilisez C, Java, C # ou même Perl; vous ne pouvez pas aller plus vite que les données ne peuvent entrer.
L'autre chose importante est que l'utilisation de la récupération de place et l'utilisation de pointeurs appropriés permettent à la machine virtuelle d'effectuer un certain nombre d'optimisations non disponibles dans d'autres langues. Par exemple, la JVM est capable de déplacer des objets sur le tas pour le défragmenter. Cela rend les allocations futures beaucoup plus rapides car le prochain indice peut simplement être utilisé plutôt que de le rechercher dans une table. Les machines virtuelles Java modernes n'ont pas non plus à réellement désallouer la mémoire; au lieu de cela, ils déplacent simplement les objets vivants lors de leur GC et la mémoire dépensée des objets morts est récupérée essentiellement gratuitement.
Cela soulève également un point intéressant à propos de C et encore plus en C ++. Il y a quelque chose d'une philosophie de conception de «Si vous n'en avez pas besoin, vous ne payez pas pour cela. Le problème est que si vous le voulez, vous finissez par payer par le nez. Par exemple, l'implémentation de vtable en Java a tendance à être bien meilleure que les implémentations C ++, donc les appels de fonctions virtuelles sont beaucoup plus rapides. D'un autre côté, vous n'avez pas d'autre choix que d'utiliser des fonctions virtuelles en Java et elles coûtent toujours quelque chose, mais dans les programmes qui utilisent beaucoup de fonctions virtuelles, le coût réduit s'additionne.
la source
Ce n'est pas tant la langue que les outils et les bibliothèques. Les bibliothèques et compilateurs disponibles pour C sont beaucoup plus anciens que pour les langages plus récents. Vous pourriez penser que cela les ralentirait, mais au contraire.
Ces bibliothèques ont été écrites à une époque où la puissance de traitement et la mémoire étaient précieuses. Ils devaient être rédigés de manière très efficace pour pouvoir fonctionner. Les développeurs de compilateurs C ont également eu longtemps à travailler dans toutes sortes d'optimisations intelligentes pour différents processeurs. La maturité et l'adoption généralisée de C lui confèrent un avantage significatif sur d'autres langues du même âge. Cela donne également à C un avantage de vitesse par rapport aux outils plus récents qui ne mettent pas autant l'accent sur les performances brutes que C le devait.
la source
Le manque d'abstraction est ce qui rend C plus rapide. Si vous écrivez une instruction de sortie, vous savez exactement ce qui se passe. Si vous écrivez une instruction de sortie en java, elle est compilée dans un fichier de classe qui est ensuite exécuté sur une machine virtuelle introduisant une couche d'abstraction. Le manque de fonctionnalités orientées objet en tant que partie du langage augmente également sa vitesse pour réduire le code généré. Si vous utilisez C comme langage orienté objet, vous effectuez tout le codage pour des choses telles que les classes, l'inharitence, etc. Cela signifie plutôt que faites quelque chose de suffisamment généralisé pour tout le monde avec la quantité de code et la pénurie de performances qui ne nécessitent que vous écrivez ce dont vous avez besoin pour faire le travail.
la source
Étonnant de voir que le vieux mythe "C / C ++ doit être plus rapide que Java car Java est interprété" est toujours vivant. Il y a des articles qui remontent à quelques années , ainsi que des articles plus récents , qui expliquent avec des concepts ou des mesures pourquoi ce n'est tout simplement pas toujours le cas .
Les implémentations de machines virtuelles actuelles (et pas seulement la JVM, soit dit en passant) peuvent tirer parti des informations recueillies lors de l'exécution du programme pour régler dynamiquement le code pendant son exécution, en utilisant une variété de techniques:
et une variété d'autres ajustements basés sur la connaissance de ce que le code fait réellement et sur les caractéristiques réelles de l'environnement dans lequel il s'exécute.
la source
Le code le plus rapide serait le code machine soigneusement fabriqué à la main. L'assembleur sera presque aussi bon. Les deux sont de très bas niveau et il faut beaucoup d'écriture de code pour faire les choses. C est un peu au-dessus de l'assembleur. Vous avez toujours la possibilité de contrôler les choses à un niveau très bas dans la machine réelle, mais il y a suffisamment d'abstraction pour l'écrire plus rapidement et plus facilement que l'assembleur. D'autres langages tels que C # et JAVA sont encore plus abstraits. Alors que l'assembleur et le code machine sont appelés langages de bas niveau, C # et JAVA (et bien d'autres) sont appelés langages de haut niveau. C est parfois appelé langage de niveau intermédiaire.
la source
Ne prenez pas le mot pour quelqu'un, regardez le désassemblage pour C et votre langue de choix dans n'importe quelle partie critique de la performance de votre code. Je pense que vous pouvez simplement regarder dans la fenêtre de démontage lors de l'exécution dans Visual Studio pour voir .Net démonté. Cela devrait être possible s'il est difficile pour Java d'utiliser windbg, mais si vous le faites avec .Net, de nombreux problèmes seront les mêmes.
Je n'aime pas écrire en C si je n'en ai pas besoin, mais je pense que la plupart des affirmations formulées dans ces réponses qui vantent la vitesse des langages autres que C peuvent être mises de côté en démontant simplement la même routine en C et dans la langue de votre choix de niveau supérieur, en particulier si de nombreuses données sont impliquées, comme cela est courant dans les applications critiques pour les performances. Fortran peut être une exception dans son domaine d'expertise, je ne sais pas. Est-ce un niveau supérieur à C?
La première fois que j'ai comparé du code JITed avec du code natif, j'ai résolu toutes les questions de savoir si le code .Net pouvait fonctionner de manière comparable au code C. Le niveau supplémentaire d'abstraction et tous les contrôles de sécurité ont un coût important. Les mêmes coûts s'appliqueraient probablement à Java, mais ne me croyez pas sur parole, essayez-le sur quelque chose où les performances sont critiques. (Quelqu'un en sait-il assez sur JITed Java pour localiser une procédure compilée en mémoire? Cela devrait certainement être possible)
la source
1) Comme d'autres l'ont dit, C fait moins pour vous. Pas de variables d'initialisation, pas de vérification des limites du tableau, pas de gestion de la mémoire, etc. Ces fonctionnalités dans d'autres langages coûtent en mémoire et en cycles CPU que C ne dépense pas.
2) Les réponses disant que C est moins abstrait et donc plus rapide ne sont qu'à moitié correctes je pense. Techniquement parlant, si vous aviez un "compilateur suffisamment avancé" pour le langage X, alors le langage X pourrait approcher ou égaler la vitesse de C. La différence avec C est que puisqu'il correspond si évidemment (si vous avez suivi un cours d'architecture) et directement au langage d'assemblage que même un compilateur naïf peut faire un travail décent. Pour quelque chose comme Python, vous avez besoin d'un compilateur très avancé pour prédire les types probables d'objets et générer du code machine à la volée - la sémantique de C est suffisamment simple pour qu'un simple compilateur puisse bien faire.
la source
Au bon vieux temps, il n'y avait que deux types de langues: compilées et interprétées.
Les langages compilés ont utilisé un «compilateur» pour lire la syntaxe du langage et le convertir en code de langage d'assemblage identique, qui pourrait être directement sur le CPU. Les langages interprétés utilisaient deux schémas différents, mais essentiellement la syntaxe du langage a été convertie en une forme intermédiaire, puis exécutée dans un "interprète", un environnement pour exécuter le code.
Ainsi, dans un sens, il y avait une autre "couche" - l'interprète - entre le code et la machine. Et, comme toujours dans un ordinateur, plus signifie plus de ressources sont utilisées. Les interprètes étaient plus lents, car ils devaient effectuer plus d'opérations.
Plus récemment, nous avons vu plus de langages hybrides comme Java, qui utilisent à la fois un compilateur et un interprète pour les faire fonctionner. C'est compliqué, mais une JVM est plus rapide, plus sophistiquée et bien plus optimisée que les anciens interprètes, donc elle représente un bien meilleur changement de performance (au fil du temps) plus proche du code compilé juste. Bien sûr, les nouveaux compilateurs ont également des astuces d'optimisation plus sophistiquées, ils ont donc tendance à générer un code bien meilleur qu'auparavant. Mais la plupart des optimisations, le plus souvent (mais pas toujours), font un certain type de compromis de sorte qu'elles ne sont pas toujours plus rapides en toutes circonstances. Comme tout le reste, rien n'est gratuit, les optimiseurs doivent donc se vanter de quelque part (bien qu'il l'utilise souvent en utilisant le CPU au moment de la compilation pour économiser le CPU à l'exécution).
Pour en revenir au C, c'est un langage simple, qui peut être compilé en assemblage assez optimisé puis exécuté directement sur la machine cible. En C, si vous incrémentez un entier, il est plus que probable que ce n'est qu'une étape d'assembleur dans le CPU, en Java cependant, cela pourrait finir par être beaucoup plus que cela (et pourrait également inclure un peu de récupération de place: -) C vous propose une abstraction beaucoup plus proche de la machine (l'assembleur est le plus proche), mais vous finissez par devoir faire beaucoup plus de travail pour le faire fonctionner et ce n'est pas aussi protégé, facile à utiliser ou sans erreur. La plupart des autres langues vous offrent une abstraction plus élevée et prennent en charge plus de détails sous-jacents pour vous, mais en échange de leurs fonctionnalités avancées, elles nécessitent plus de ressources pour fonctionner. Au fur et à mesure que vous généralisez certaines solutions, vous devez gérer une gamme plus large d'informatique,
Paul.
la source
++i
pourrait compiler pour "ajouter [ebp-8], 1". Cela ne veut pas dire que la récupération, l'incrémentation, le stockage ne se produisent toujours pas, mais cela est pris en charge par le processeur et n'est qu'une instruction, comme l'a dit Paul.Mis à part les techniques d'optimisation avancées telles que l' optimisation des points chauds , les méta-algorithmes précompilés et diverses formes de parallélisme , la vitesse fondamentale d'un langage est fortement corrélée à la complexité implicite en arrière-plan nécessaire pour prendre en charge les opérations qui seraient généralement être spécifié dans les boucles internes .
Le plus évident est peut-être la vérification de la validité des références de mémoire indirectes, telles que la vérification des pointeurs
null
et la vérification des index par rapport aux limites des tableaux. La plupart des langages de haut niveau effectuent ces vérifications implicitement, mais pas C. Cependant, ce n'est pas nécessairement une limitation fondamentale de ces autres langages - un compilateur suffisamment intelligent peut être capable de supprimer ces vérifications des boucles internes d'un algorithme à travers une certaine forme de mouvement de code invariant en boucle .L'avantage le plus fondamental de C (et dans une mesure similaire le C ++ étroitement lié) est une forte dépendance à l' allocation de mémoire basée sur la pile , qui est intrinsèquement rapide pour l'allocation, la désallocation et l'accès. En C (et C ++), la pile d'appels principale peut être utilisée pour l'allocation de primitives, de tableaux et d'agrégats (
struct
/class
).Alors que C offre la possibilité d' allouer dynamiquement de la mémoire de taille et de durée de vie arbitraires (en utilisant le soi-disant «tas»), cela est évité par défaut (la pile est utilisée à la place).
De façon alléchante, il est parfois possible de répliquer la stratégie d'allocation de mémoire C dans les environnements d'exécution d'autres langages de programmation. Cela a été démontré par asm.js , qui permet au code écrit en C ou C ++ d'être traduit en un sous-ensemble de JavaScript et de s'exécuter en toute sécurité dans un environnement de navigateur Web - avec une vitesse quasi-native.
Comme un peu à part, un autre domaine où C et C ++ surpassent la plupart des autres langages pour la vitesse est la capacité à s'intégrer de manière transparente avec les jeux d'instructions machine natifs. Un exemple notable de ceci est la disponibilité (dépendante du compilateur et de la plate-forme) des intrinsèques SIMD qui prennent en charge la construction d'algorithmes personnalisés qui tirent parti du matériel de traitement parallèle désormais presque omniprésent - tout en utilisant les abstractions d'allocation de données fournies par le langage (inférieur -l'allocation des registres de niveau est gérée par le compilateur).
la source
J'ai trouvé une réponse sur le lien expliquant pourquoi certains langages sont plus rapides et certains plus lents, j'espère que cela clarifiera davantage pourquoi C ou C ++ est plus rapide que d'autres, Il existe également d'autres langages plus rapides que C, mais nous ne pouvons pas utilisez-les tous. Quelques explications -
L'une des principales raisons pour lesquelles Fortran reste important est qu'il est rapide: les routines de calcul des nombres écrites en Fortran ont tendance à être plus rapides que les routines équivalentes écrites dans la plupart des autres langues. Les langages qui concurrencent Fortran dans cet espace - C et C ++ - sont utilisés parce qu'ils sont compétitifs avec cette performance.
Cela soulève la question: pourquoi? En quoi C ++ et Fortran les rendent-ils rapides, et pourquoi surpassent-ils les autres langages populaires, tels que Java ou Python?
Interpréter ou compiler Il existe de nombreuses façons de catégoriser et de définir les langages de programmation, selon le style de programmation qu'ils encouragent et les fonctionnalités qu'ils offrent. En ce qui concerne les performances, la plus grande distinction est entre les langages interprétés et les langages compilés.
La fracture n'est pas difficile; il y a plutôt un spectre. À une extrémité, nous avons des langages compilés traditionnels, un groupe qui comprend Fortran, C et C ++. Dans ces langages, il existe une étape de compilation discrète qui traduit le code source d'un programme sous une forme exécutable que le processeur peut utiliser.
Ce processus de compilation comporte plusieurs étapes. Le code source est analysé et analysé. Les erreurs de codage de base telles que les fautes de frappe et les fautes d'orthographe peuvent être détectées à ce stade. Le code analysé est utilisé pour générer une représentation en mémoire, qui peut également être utilisée pour détecter des erreurs - cette fois, des erreurs sémantiques, telles que des fonctions d'appel qui n'existent pas, ou essayer d'effectuer des opérations arithmétiques sur des chaînes de texte.
Cette représentation en mémoire est ensuite utilisée pour piloter un générateur de code, la partie qui produit du code exécutable. L'optimisation de code, pour améliorer les performances du code généré, est effectuée à différents moments de ce processus: des optimisations de haut niveau peuvent être effectuées sur la représentation du code, et des optimisations de niveau inférieur sont utilisées sur la sortie du générateur de code.
L'exécution effective du code se produit plus tard. L'ensemble du processus de compilation est simplement utilisé pour créer quelque chose qui peut être exécuté.
À l'opposé, nous avons des interprètes. Les interprètes incluront une étape d'analyse similaire à celle du compilateur, mais celle-ci est ensuite utilisée pour piloter l'exécution directe, le programme étant exécuté immédiatement.
L'interprète le plus simple a en son sein du code exécutable correspondant aux différentes fonctionnalités prises en charge par le langage - il aura donc des fonctions pour ajouter des nombres, joindre des chaînes, quoi que ce soit d'autre dans un langage donné. En analysant le code, il recherchera la fonction correspondante et l'exécutera. Les variables créées dans le programme seront conservées dans une sorte de table de recherche qui mappe leurs noms à leurs données.
L'exemple le plus extrême du style interprète est quelque chose comme un fichier batch ou un script shell. Dans ces langages, le code exécutable n'est souvent même pas intégré à l'interpréteur lui-même, mais plutôt à des programmes autonomes séparés.
Alors pourquoi cela fait-il une différence dans les performances? En général, chaque couche d'indirection réduit les performances. Par exemple, le moyen le plus rapide pour ajouter deux nombres est d'avoir ces deux nombres dans les registres du processeur et d'utiliser l'instruction d'ajout du processeur. C'est ce que les programmes compilés peuvent faire; ils peuvent mettre des variables dans des registres et tirer parti des instructions du processeur. Mais dans les programmes interprétés, ce même ajout peut nécessiter deux recherches dans une table de variables pour récupérer les valeurs à ajouter, puis appeler une fonction pour effectuer l'ajout. Cette fonction peut très bien utiliser la même instruction de processeur que celle utilisée par le programme compilé pour effectuer l'addition réelle, mais tout le travail supplémentaire avant que l'instruction puisse réellement être utilisée ralentit les choses.
Si vous voulez en savoir plus, veuillez vérifier la source
la source
Certains algorithmes C ++ sont plus rapides que C, et certaines implémentations d'algorithmes ou de modèles de conception dans d'autres langages peuvent être plus rapides que C.
Lorsque les gens disent que C est rapide et passent ensuite à parler d'un autre langage, ils utilisent généralement les performances de C comme référence.
la source
Avec les compilateurs d'optimisation modernes, il est très peu probable qu'un programme C pur soit beaucoup plus rapide que le code .net compilé, voire pas du tout. Avec l'amélioration de la productivité que les frameworks comme .net fournissent au développeur, vous pouvez faire des choses en une journée qui prenait habituellement des semaines ou des mois en C. régulier Couplé avec le coût bon marché du matériel par rapport au salaire d'un développeur, il est tout de même beaucoup moins cher d'écrire les trucs dans un langage de haut niveau et lancer du matériel à n'importe quelle lenteur.
La raison pour laquelle Jeff et Joel parlent de C comme étant le "vrai programmeur" est parce qu'il n'y a pas de main dans C. Vous devez allouer votre propre mémoire, désallouer cette mémoire, faire vos propres vérifications de limites, etc. Il n'y a rien de tel comme nouvel objet (); Il n'y a pas de garbage collection, de classes, de POO, de structures d'entités, de LINQ, de propriétés, d'attributs, de champs ou quoi que ce soit de ce genre. Vous devez savoir des choses comme l'arithmétique des pointeurs et comment déréférencer un pointeur. Et, d'ailleurs, sachez et comprenez ce qu'est un pointeur. Vous devez savoir ce qu'est un cadre de pile et quel est le pointeur d'instruction. Vous devez connaître le modèle de mémoire de l'architecture CPU sur laquelle vous travaillez. Il y a beaucoup de compréhension implicite de l'architecture d'un micro-ordinateur (généralement lemicro-ordinateur sur lequel vous travaillez) lors de la programmation en C qui n'est tout simplement pas présent ni nécessaire lors de la programmation en quelque chose comme C # ou Java. Toutes ces informations ont été déchargées sur le programmeur du compilateur (ou VM).
la source
C'est la différence entre automatique et manuel, les langues de niveau supérieur sont des abstractions ainsi automatisées. C / C ++ sont contrôlés et manipulés manuellement, même le code de vérification des erreurs est parfois un travail manuel.
C et C ++ sont également des langages compilés, ce qui signifie que rien de tout cela ne fonctionne partout, ces langages doivent être affinés pour le matériel avec lequel vous travaillez, ajoutant ainsi une couche supplémentaire de gotcha. Bien que cela devienne légèrement flou maintenant, les compilateurs C / C ++ devenant plus courants sur toutes les plates-formes. Vous pouvez effectuer des compilations croisées entre plates-formes. Ce n'est toujours pas une situation qui s'exécute partout, vous demandez essentiellement au compilateur A de compiler avec le même code différent du compilateur B.
Les langages C ne sont pas censés être faciles à comprendre ou à raisonner, c'est aussi pourquoi ils sont appelés langages systèmes. Ils sont sortis avant toutes ces bêtises d'abstraction de haut niveau. C'est aussi pourquoi ils ne sont pas utilisés pour la programmation Web frontale. Ils ne sont tout simplement pas adaptés à la tâche, leur moyen de résoudre des problèmes complexes qui ne peuvent pas être résolus avec l'outillage de langage conventionnel.
C'est pourquoi vous obtenez des trucs fous comme (micro-architectures, pilotes, physique quantique, AAA Games, systèmes d'exploitation) il y a des choses pour lesquelles le C et le C ++ sont bien adaptés. La vitesse et le nombre croquant étant les domaines principaux.
la source
C est rapide car il s'agit d'un langage de bas niveau compilé en mode natif. Mais C n'est pas le plus rapide. La référence récursive de Fibonacci montre que la rouille, le cristal et le Nim peuvent être plus rapides.
la source
Il y a plusieurs raisons, notamment:
la source