Pourquoi C est-il si rapide et pourquoi les autres langues ne sont-elles pas aussi rapides ou rapides?

En écoutant le podcast de StackOverflow, le jab n’arrête pas d’écrire que les “vrais programmeurs” écrivent en C, et que C est beaucoup plus rapide car il est “proche de la machine”. Laissant l’ancienne assertion pour un autre article, 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 se comstackr en binary qui s’exécute aussi vite que C?

Il n’y a pas grand chose de spécial à propos de C. C’est l’une des raisons pour lesquelles c’est rapide.

Langues plus récentes qui prennent en charge la récupération de place , la saisie dynamic et d’autres fonctions facilitant l’écriture de programmes pour le programmeur.

Le problème réside dans le fait que le traitement supplémentaire entraîne une dégradation des performances de l’application. C n’a rien de cela, ce qui signifie qu’il n’y a pas de surcharge, mais cela signifie que le programmeur doit pouvoir allouer de la mémoire et les libérer pour éviter les memory leaks , et 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 Common Language Runtime) ont amélioré les performances au fil des années avec des avantages tels que la compilation juste-à-temps . bytecode pour obtenir de meilleures performances.

Il y a un compromis que les concepteurs de C ont fait. C’est-à-dire qu’ils ont pris la décision de mettre la vitesse au-dessus de la sécurité. C ne veut pas

  • Vérifier les limites de l’index du tableau
  • Rechercher les valeurs de variable non initialisées
  • Vérifiez les memory leaks
  • Rechercher le déréférencement du pointeur null

Lorsque vous indexez dans un tableau, en Java, il faut un appel de méthode dans la machine virtuelle, un contrôle lié 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 n’exige pas que memcpy vérifie si les régions à copier se chevauchent. Ce n’est pas conçu comme un langage pour programmer une application professionnelle.

Mais ces décisions de conception ne sont pas des bugs dans le langage C. Ils sont conçus pour permettre aux compilateurs et aux rédacteurs de bibliothèques d’exécuter toutes les tâches de l’ordinateur. Voici l’esprit de C comment le document C Justification s’explique:

Le code C peut être non portable. Bien qu’il s’efforce de donner aux programmeurs l’opportunité d’écrire des programmes réellement portables, le Comité ne veut pas forcer les programmeurs à écrire de manière portable, pour empêcher l’utilisation de C comme «assembleur de haut niveau»: le code est l’une des forces de C.

Garder l’esprit de C. Le Comité a gardé comme objective majeur de préserver l’esprit traditionnel de C. Il y a plusieurs facettes de l’esprit de C, mais l’essence est un sentiment communautaire des principes sous-jacents sur lesquels le langage C est basé. Certaines des facettes de l’esprit de C peuvent être résumées en phrases comme

  • Faites confiance au programmeur.
  • N’empêchez pas le programmeur de faire ce qui doit être fait.
  • Gardez la langue petite et simple.
  • Fournir une seule façon de faire une opération.
  • Faites-le rapidement, même s’il n’est pas garanti qu’il soit portable.

Le dernier proverbe a besoin d’une petite explication. Le potentiel de génération de code efficace est l’un des atouts les plus importants de C. Pour garantir qu’aucune explosion de code ne se produise pour une opération qui semble très simple, de nombreuses opérations sont définies comme le matériel de la machine cible plutôt que par une règle générale abstraite. Un exemple de cette volonté de vivre avec ce que fait la machine peut être vu dans les règles qui régissent l’élargissement des objects char à utiliser dans les expressions: si les valeurs des objects char s’élargissent à des quantités signées ou non signées efficace sur la machine cible.

Si vous passez un mois à construire quelque chose en C qui tourne en 0.05 secondes, et que je passe une journée à écrire la même chose en Java, et que ça tourne en 0.10 secondes, alors C est-il vraiment plus rapide?

Mais pour répondre à votre question, un code C bien écrit fonctionnera généralement plus vite qu’un code bien écrit dans d’autres langues, car une partie de l’écriture du code C “bien” inclut des optimisations manuelles au niveau de la machine.

Bien que les compilateurs soient très intelligents, ils ne sont pas encore en mesure de créer du code concurrençant des algorithmes massés manuellement (en supposant que les “mains” appartiennent à un bon programmeur C).

Modifier:

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:

function RemoveAllAFromB(a, b: ssortingng): ssortingng; var before, after :ssortingng; begin Result := b; if 0 < Pos(a,b) then begin before := Copy(b,1,Pos(a,b)-Length(a)); after := Copy(b,Pos(a,b)+Length(a),Length(b)); Result := before + after; Result := RemoveAllAFromB(a,Result); //recursive end; end; 

et dans CI écrivez ceci:

 char *s1, *s2, *result; /* original ssortingngs and the result ssortingng */ int len1, len2; /* lengths of the ssortingngs */ for (i = 0; i < len1; i++) { for (j = 0; j < len2; j++) { if (s1[i] == s2[j]) { break; } } if (j == len2) { /* s1[i] is not found in s2 */ *result = s1[i]; result++; /* assuming your result array is long enough */ } } 

Mais combien d’optimisations existe-t-il dans la version C? Nous prenons beaucoup de décisions sur la mise en œuvre que je ne pense pas dans la version Delphi. Comment une chaîne est-elle implémentée? En Delphi, je ne le vois pas. En C, j'ai décidé que ce serait un pointeur vers un tableau d'entiers ASCII, que nous appelons des caractères. En C, nous testons l'existence d'un personnage un par un. Dans 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 toutes les quelques lignes de code. Il s’agit d’un exécutable fabriqué à la main et optimisé à la main.

Je ne l’ai pas encore vu, alors je vais le dire: C a tendance à être plus rapide car presque tout le rest est écrit en C.

Java est construit sur C, Python est construit sur C (ou Java, ou .NET, etc.), Perl l’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éteurs sont écrits en C. Certaines choses sont encore écrites en langage assembleur, ce qui tend à être encore plus rapide. De plus en plus de choses sont écrites dans autre chose, qui est lui-même écrit en C.

Chaque instruction que vous écrivez dans d’autres langages (pas dans Assembly) est généralement implémentée sous plusieurs instructions dans C, qui sont compilées en code machine natif. Comme ces autres langages ont tendance à exister pour obtenir un niveau d’abstraction plus élevé que C, les instructions supplémentaires requirejses dans 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 leurs noms sont la vitesse et la taille .

Personnellement, j’ai écrit littéralement des dizaines de langues couvrant la majeure partie du spectre disponible, et j’ai personnellement recherché la magie que vous suggérez:

Comment puis-je avoir mon gâteau et le manger aussi? Comment puis-je jouer avec des abstractions de haut niveau dans ma langue préférée, puis accéder aux détails concrets de C pour la vitesse?

Après quelques années de recherche, ma réponse est Python (sur C). Vous voudrez peut-être y jeter un coup d’oeil. Par ailleurs, vous pouvez également accéder à Assembly depuis Python (avec une aide mineure d’une bibliothèque spéciale).

D’un autre côté, un code incorrect 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 apporter des portions de code de langage de niveau supérieur proches du niveau de performance de la technologie brute C. Mais, pour la plupart des applications, votre programme passe le plus clair de son temps à attendre des personnes ou du matériel.

Prendre plaisir.

Il y a beaucoup de questions là-dedans – la plupart du temps, je ne suis pas qualifié pour répondre. Mais pour ce dernier:

Qu’est-ce qui empêche d’autres langages de se comstackr en binary qui s’exécute aussi vite que C?

En un mot, l’abstraction.

C est seulement un ou deux niveaux d’abstraction du langage machine. Java et les langages .Net sont au minimum à 3 niveaux d’abstraction de l’assembleur. Je ne suis pas sûr pour Python et Ruby.

En règle générale, plus il y a de jouets programmeurs (types de données complexes, etc.), plus vous êtes loin du langage machine et plus vous devez effectuer de traductions.

Je pars ici et là mais c’est l’essentiel.

Mise à jour – Il y a de bons commentaires sur cet article avec plus de détails.

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 objects (en particulier la reflection) ou les chaînes peuvent avoir des coûts qui ne sont pas évidents.

Deux langages généralement compilés en binarys aussi rapides que C sont Standard ML (en utilisant le compilateur MLton ) et Objective Caml . Si vous consultez le jeu de benchmarks, vous verrez que pour certains benchmarks, comme les arbres binarys, la version OCaml est plus rapide que C. (je n’ai pas trouvé d’entrées MLton). c’est, comme il est dit, un jeu, les résultats reflètent souvent combien d’effort les gens ont mis au réglage du code.

C n’est pas toujours plus rapide.

C est plus lent que, par exemple, le Fortran moderne.

C est souvent plus lent que Java pour certaines choses. (Surtout après que le compilateur JIT est passé à votre code)

C permet à l’aliasing de pointeur de 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 provoque des arrêts de récupération de données. Ow.

L’hypothèse selon laquelle l’arithmétique du pointeur fonctionne vraiment entraîne des performances excessivement longues sur certaines familles de processeurs (en particulier le PIC)!

Fondamentalement, lorsque vous obtenez une unité vectorielle ou un compilateur parallélisant, C pue et Fortran moderne s’exécute plus rapidement.

Les astuces du programmeur en C comme le thunking (modifier l’exécutable à la volée) provoquent des stalls de pré-extraction du processeur.

Vous obtenez la dérive?

Et notre bon ami, le x86, exécute un jeu d’instructions que ces jours-ci ont peu de rapport avec l’architecture du processeur. Shadow enregistre, optimiseurs de magasins de chargement, tous dans le processeur. Donc, C est alors proche du métal virtuel. Le vrai métal, Intel ne vous laisse pas voir. (Historiquement, les processeurs VLIW étaient un peu un buste, peut-être que ce n’est pas si grave.)

Si vous programmez en C sur un DSP haute performance (peut-être un DSP TI?), Le compilateur doit faire des choses délicates pour dérouler le C entre les différentes unités d’exécution parallèles. Donc, dans ce cas, C n’est pas proche du metal, mais il est proche du compilateur, ce qui fera l’optimisation complète du programme. Bizarre.

Et enfin, certains processeurs (www.ajile.com) exécutent des bytecodes Java dans le matériel. C serait un PITA à utiliser sur cette CPU.

Qu’est-ce qui empêche d’autres langages de se comstackr en binary qui s’exécute aussi vite que C?

Rien. Les langages modernes tels que Java ou .NET lang sont davantage axés sur la productivité des programmeurs que sur les performances. Le matériel est bon marché aujourd’hui. La compilation vers une représentation intermédiaire donne également beaucoup de bonus, tels que la sécurité, la portabilité, etc. NET CLR peut tirer parti de différents matériels – par exemple, vous n’avez pas besoin d’optimiser / recomstackr manuellement le programme pour utiliser le jeu d’instructions SSE.

Les principaux facteurs sont que c’est un langage typé statiquement et qui est compilé en code machine. De plus, comme il s’agit d’un langage de bas niveau, il ne fait généralement pas ce que vous ne lui dites pas.

Ce sont quelques autres facteurs qui viennent à l’esprit.

  • Les variables ne sont pas automatiquement initialisées
  • Vérification des limites sur les tableaux
  • Manipulation non contrôlée du pointeur
  • Pas de vérification de dépassement d’entier
  • Variables typées statiquement
  • Les appels de fonction sont statiques (sauf si vous utilisez des pointeurs de fonction)
  • Les auteurs du compilateur ont eu beaucoup de temps pour améliorer le code d’optimisation. De plus, les gens programment en C dans le but d’obtenir les meilleures performances, il y a donc une pression pour optimiser le code.
  • Des parties de la spécification de langage sont définies par l’implémentation, de sorte que les compilateurs sont libres de faire les choses de la manière la plus optimale

Cependant, la plupart des langages de type statique peuvent être compilés aussi rapidement ou plus rapidement que C, surtout s’ils peuvent supposer que C ne le peut pas à cause d’un alias de pointeur, etc.

Je suppose que vous avez oublié que le langage d’assemblage est aussi une langue 🙂

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 fonctionne 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’elle est conçue de cette manière. Il vous permet de faire beaucoup de choses “de bas niveau” qui aident le compilateur à optimiser le code. Ou, dirons-nous, le programmeur est responsable de l’optimisation du code. Mais c’est souvent compliqué et sujet aux erreurs.

D’autres langages, comme d’autres déjà mentionnés, mettent davantage l’accent sur la productivité du programmeur. On pense généralement que le temps de programmation est beaucoup plus cher que le temps machine (même dans le passé). Il est donc tout à fait logique de réduire le temps que les programmeurs consacrent à l’écriture et au débogage des programmes au lieu de la durée d’exécution des programmes. Pour ce faire, vous sacrifierez un peu sur ce que vous pouvez faire pour accélérer le programme car beaucoup de choses sont automatisées.

C ++ est plus rapide en moyenne (car il était initialement un super ensemble de C). Cependant, pour des tests spécifiques, il existe souvent un autre langage plus rapide.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/

fannjuch-redux était le plus rapide à Scala

n-body et fasta étaient plus rapides à Ada.

spectral-norm était la plus rapide chez Fortran.

reverse-complement , mandelbrot et pidigits ont été les plus rapides dans l’ATS.

regex-dna était le plus rapide en JavaScript.

chameneou-redux était le plus rapide est Java 7.

thread-ring était le plus rapide chez Haskell.

Les autres tests ont été les plus rapides en C ou C ++.

Je ne pense pas que quiconque ait mentionné le fait que beaucoup plus d’efforts ont été faits dans les compilateurs C que tout autre compilateur, à l’exception peut-être de Java.

C est extrêmement optimisable pour la plupart des raisons déjà mentionnées – plus que presque toutes les autres langues. Donc, si le même effort est consenti à 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 un effort, pourrait être optimisé mieux que C et nous pourrions donc voir des implémentations qui produisent des binarys plus rapides. Je pense au numérique D, car le créateur a pris soin de créer un langage potentiellement mieux optimisé que le langage C. Il se peut que d’autres langages aient cette possibilité. Cependant, je ne peux pas imaginer que les compilateurs soient plus rapides que quelques-uns des meilleurs compilateurs. J’aimerais bien avoir tort.

Je pense que le véritable «fruit à scope de main» sera dans des langues conçues pour être faciles à optimiser pour les humains. Un programmeur compétent peut accélérer n’importe quel langage, mais parfois, il faut faire des choses ridicules ou utiliser des concepts non naturels pour y arriver. Bien que cela demande toujours un effort, un bon langage devrait produire un code relativement rapide sans avoir à être obsédé par la manière exacte dont le programme est écrit.

Il est également important (du moins pour moi) que le code du cas le plus défavorable ait tendance à être rapide. Il existe de nombreuses «preuves» sur le Web indiquant 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 se passer. Avec Java, la vitesse sera “probablement” inférieure à 15%, généralement inférieure à 25%, mais dans certains cas, elle sera bien pire. Tous les cas où il est tout aussi rapide ou en quelques pour cent sont généralement dus à la plupart du temps passé dans le code de la bibliothèque, qui est fortement optimisé de toute façon.

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. Beaucoup d’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 des langages interprétés comme Java ou Ruby instructions que vous ne voyez jamais – la machine virtuelle ou l’interprète.

C’est en fait un mensonge perpétuel. 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 performant.

Un grand trou que les gens ont tendance à oublier est que le programme doit bloquer pour une sorte d’E / S, comme la saisie d’un utilisateur dans n’importe quel programme graphique. Dans ces cas-là, peu importe la langue que vous utilisez, vous êtes limité par la vitesse à laquelle les données peuvent entrer, 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 peuvent entrer.

L’autre point important est que l’utilisation de la récupération de place et l’absence de pointeurs appropriés permettent à la machine virtuelle d’effectuer un certain nombre d’optimisations non disponibles dans d’autres langages. Par exemple, la machine virtuelle Java est capable de déplacer des objects sur le tas pour la défragmenter. Cela rend les atsortingbutions futures beaucoup plus rapides, car le prochain index peut simplement être utilisé plutôt que de le rechercher dans un tableau. Les JVM modernes n’ont pas non plus besoin de désallouer de la mémoire; au lieu de cela, ils déplacent simplement les objects vivants autour de leur GC et la mémoire épuisée des objects morts est récupérée essentiellement gratuitement.

Cela soulève également un point intéressant sur C et plus encore 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 vtable en Java a tendance à être bien meilleure que les implémentations C ++, donc les appels de fonction virtuels sont beaucoup plus rapides. D’un autre côté, vous n’avez pas d’autre choix que d’utiliser les 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’ajoute.

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). C’est indéniable que:

  • De nombreux autres langages fournissent des fonctionnalités automatiques que nous tenons pour acquises. La vérification des limites, la vérification du type d’exécution et la gestion automatique de la mémoire, par exemple, ne sont pas gratuites. Il y a au moins certains coûts associés à ces fonctionnalités, auxquelles nous ne pouvons pas penser, ni même réaliser, lors de l’écriture de code utilisant ces fonctionnalités.
  • Le passage de la source à la machine n’est souvent pas aussi direct dans d’autres langues que dans C.
  • OTOH, dire que le code C compilé s’exécute plus rapidement que les autres codes écrits dans d’autres langages est une généralisation qui n’est pas toujours vraie. Les contre-exemples sont faciles à trouver (ou à inventer).

Malgré tout, il y a quelque chose d’autre que j’ai remarqué qui, je pense, affecte la performance comparative de C par rapport à beaucoup d’autres langues, 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.

À titre d’exemple, considérons un programme Windows simple dans lequel une seule fenêtre principale est créée. La version AC remplit une WNDCLASS[EX] qui serait transmise à RegisterClass[Ex] , puis appelle CreateWindow[Ex] et entre une boucle de message. Code hautement simplifié et abrégé:

 WNDCLASS wc; MSG msg; wc.style = 0; wc.lpfnWndProc = &WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = "MainWndCls"; RegisterClass(&wc); CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); while(GetMessage(&msg, NULL, 0, 0)){ TranslateMessage(&msg); DispatchMessage(&msg); } 

Un programme équivalent en C # pourrait être une seule ligne de code:

 Application.Run(new Form()); 

Cette ligne de code fournit toutes les fonctionnalités utilisées par 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 (comparée à celles utilisées dans un projet C typique) a fait beaucoup de travail pour nous, libérant notre temps pour écrire beaucoup plus de fragments de code qui nous semblent courts, mais qui impliquent de nombreuses étapes.

Mais une bibliothèque riche qui facilite et accélère le codage de code n’est pas vraiment mon objective. Mon point est plus évident lorsque vous commencez à examiner ce qui se passe réellement lorsque notre petit one-liner s’exécute. Pour vous amuser quelque temps, activez l’access à la source .NET dans Visual Studio 2008 ou supérieur et accédez à la ligne simple ci-dessus. Un des petits joyaux amusants que vous rencontrerez est ce commentaire dans getter pour Control.CreateParams :

 // In a typical control this is accessed ten times to create and show a control. // It is a net memory savings, then, to maintain a copy on control. // if (createParams == null) { createParams = new CreateParams(); } 

Dix fois Les informations à peu près équivalentes à la sum de ce qui est stocké dans une structure WNDCLASSEX et à celles transmises à CreateWindowEx sont extraites de la classe Control dix fois avant d’ être stockées dans une structure WNDCLASSEX et transmises à RegisterClassEx et CreateWindowEx .

Globalement, le nombre d’instructions exécutées pour effectuer cette tâche très basique est de 2 à 3 fois plus grand en C # qu’en C. Cela s’explique en partie par l’utilisation d’une bibliothèque riche en fonctionnalités, qui est nécessairement généralisée par rapport à notre code C simple qui fait exactement ce dont nous avons besoin et rien de plus. Mais cela tient en partie au fait que la nature modulaire et orientée object de .NET Framework se prête à de nombreuses répétitions d’exécution qui sont souvent évitées par une approche procédurale.

Je n’essaie 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. Je faisais la plupart de mon développement en C, plus tard en C ++, et plus récemment en C #. De même, avant C, j’ai surtout utilisé l’assemblage. Et à chaque étape “supérieure” de mon langage, j’écris des programmes plus efficaces, plus faciles à maintenir et plus robustes en moins de temps. Ils ont cependant tendance à exécuter un peu plus lentement.

Le manque d’abstraction est ce qui rend C plus rapide. Si vous écrivez une déclaration de sortie, vous savez exactement ce qui se passe. Si vous écrivez une instruction de sortie dans Java, elle est compilée dans un fichier de classe qui est ensuite exécuté sur une machine virtuelle en introduisant une couche d’abstraction. The lack of object oriented features as a part of the language also increases it’s speed do to less code being generated. If you use C as an object oriented language then you are doing all the coding for things such as classes, inharitence, etc. This means rather then make something generalized enough for everyone with the amount of code and the performance penelty that requires you only write what you need to get the job done.

Amazing to see the old “C/C++ must be faster than Java because Java is interpreted” myth is still alive and kicking. There are articles going back a few years , as well as more recent ones , that explain with concepts or measurements why this simply isn’t always the case .

Current virtual machine implementations (and not just the JVM, by the way) can take advantage of information gathered during program execution to dynamically tune the code as it runs, using a variety of techniques:

  • rendering frequent methods to machine code,
  • inlining small methods,
  • adjustment of locking

and a variety of other adjustments based on knowing what the code is actually doing, and on the actual characteristics of the environment in which it’s running.

The fastest running code would be carefully hand crafted machine code. Assembler will be almost as good. Both are very low level and it takes a lot of writing code to do things. C is a little above assembler. You still have the ability to control things at a very low level in the actual machine, but there is enough abstraction make writing it faster and easier then assembler. Other languages such as C# and JAVA are even more abstract. While Assembler and machine code are called low level languages, C# and JAVA (and many others) are called high level languages. C is sometimes called a middle level language.

It’s not so much about the language as the tools and libraries. The available libraries and comstackrs for C are much older than for newer languages. You might think this would make them slower, but au contraire.

These libraries were written at a time when processing power and memory were at a premium. They had to be written very efficiently in order to work at all. Developers of C comstackrs have also had a long time to work in all sorts of clever optimizations for different processors. C’s maturity and wide adoption makes for a signficant advantage over other languages of the same age. It also gives C a speed advantage over newer tools that don’t emphasize raw performance as much as C had to.

I know plenty of people have said it in a long winded way, but:

C is faster because it does less (for you).

Back in the good ole days, there were just two types of languages: comstackd and interpreted.

Comstackd languages utilized a “comstackr” to read the language syntax and convert it into identical assembly language code, which could than just directly on the CPU. Interpreted languages used a couple of different schemes, but essentially the language syntax was converted into an intermediate form, and then run in a “interpreter”, an environment for executing the code.

Thus, in a sense, there was another “layer” — the interpreter — between the code and the machine. And, as always the case in a computer, more means more resources get used. Interpreters were slower, because they had to perform more operations.

More recently, we’ve seen more hybrid languages like Java, that employ both a comstackr and an interpreter to make them work. It’s complicated, but a JVM is faster, more sophisticated and way more optimized than the old interpreters, so it stands a much better change of performing (over time) closer to just straight comstackd code. Of course, the newer comstackrs also have more fancy optimizing sortingcks so they tend to generate way better code than they used to as well. But most optimizations, most often (although not always) make some type of trade-off such that they are not always faster in all circumstances. Like everything else, nothing comes for free, so the optimizers must get their boast from somewhere (although often times it using comstack-time CPU to save runtime CPU).

Getting back to C, it is a simple language, that can be comstackd into fairly optimized assembly and then run directly on the target machine. In C, if you increment an integer, it’s more than likely that it is only one assembler step in the CPU, in Java however, it could end up being a lot more than that (and could include a bit of garbage collection as well 🙂 C offers you an abstraction that is way closer to the machine (assembler is the closest), but you end up having to do way more work to get it going and it is not as protected, easy to use or error friendly. Most other languages give you a higher abstraction and take care of more of the underlying details for you, but in exchange for their advanced functionality they require more resources to run. As you generalize some solutions, you have to handle a broader range of computing, which often requires more resources.

Paul.

Don’t take someones word for it, look at the dissassembly for both C and your language-of-choice in any performance critical part of your code. I think you can just look in the disassembly window at runtime in Visual Studio to see disassembled .Net. Should be possible if sortingcky for Java using windbg, though if you do it with .Net many of the issues would be the same.

I don’t like to write in C if I don’t need to, but I think many of the claims made in these answers that tout the speed of languages other than C can be put aside by simply disassembling the same routine in C and in your higher level language of choice, especially if lots of data is involved as is common in performance critical applications. Fortran may be an exception in its area of expertise, don’t know. Is it higher level than C?

First time I did compared JITed code with native code resolved any and all questions whether .Net code could run comparably to C code. The extra level of abstraction and all the safety checks come with a significant cost. Same costs would probably apply to Java, but don’t take my word for it, try it on something where performance is critical. (Anyone know enough about JITed Java to locate a comstackd procedure in memory? It should certainly be possible)

Some C++ algorithms are faster than C, and some implementations of algorithms or design patterns in other languages can be faster than C.

When people say that C is fast, and then move on to talking about some other language, they are generally using C’s performance as a benchmark.

With modern optimizing comstackrs, it’s highly unlikely that a pure C program is going to be all that much faster than comstackd .net code, if at all. With the productivity enhancement that frameworks like .net provide the developer, you can do things in a day that used to take weeks or months in regular C. Coupled with the cheap cost of hardware compared to a developer’s salary, it’s just WAY cheaper to write the stuff in a high-level language and throw hardware at any slowness.

The reason Jeff and Joel talk about C being the “real programmer” language is because there is no hand-holding in C. You must allocate your own memory, deallocate that memory, do your own bounds-checking, etc. There’s no such thing as new object(); There’s no garbage collection, classes, OOP, entity frameworks, LINQ, properties, atsortingbutes, fields, or anything like that. You have to know things like pointer arithmetic and how to dereference a pointer. And, for that matter, know and understand what a pointer is. You have to know what a stack frame is and what the instruction pointer is. You have to know the memory model of the CPU architecture you’re working on. There is a lot of implicit understanding of the architecture of a microcomputer (usually the microcomputer you’re working on) when programming in C that simply is not present nor necessary when programming in something like C# or Java. All of that information has been off-loaded to the comstackr (or VM) programmer.

1) As others have said, C does less for you. No initializing variables, no array bounds checking, no memory management, etc. Those features in other languages cost memory and CPU cycles that C doesn’t spend.

2) Answers saying that C is less abstracted and therefore faster are only half correct I think. Technically speaking, if you had a “sufficiently advanced comstackr” for language X, then language X could approach or equal the speed of C. The difference with C is that since it maps so obviously (if you’ve taken an architecture course) and directly to assembly language that even a naive comstackr can do a decent job. For something like Python, you need a very advanced comstackr to predict the probable types of objects and generate machine code on the fly — C’s semantics are simple enough that a simple comstackr can do well.

It’s the difference between automatic and manual, higher level languages are abstractions thus automated. C/C++ are manually controlled and handled, even error checking code is sometimes a manual labor.

C and C++ are also comstackd languages which means none of that run everywhere business, these languages have to be fine tuned for the hardware you work with thus adding an extra layer of gotcha. Though this is slightly fazing out now as C/C++ comstackrs are becoming more common across all platforms. You can do cross compilations between platforms. It’s still not a run everywhere situation, your basically instructing comstackr A to comstack against comstackr B same code different architecture.

Bottom line C languages are not meant to be easy to understand or reason, this is also why their referred to as systems languages. They came out before all this high level abstraction nonsense. This is also why they are not used for front end web programming. Their just not suited to the task, their mean to solve complex problems that can’t be resolved with conventional language tooling.

This is why you get crazy stuff like (micro-architectures, drivers, quantum physics, AAA Games, operating systems) there are things C and C++ are just well suited for. Speed and number crunching being the chief areas.

Setting aside advanced optimization techniques such as hot-spot optimization , pre-comstackd meta-algorithms , and various forms of parallelism , the fundamental speed of a language correlates strongly with the implicit behind-the-scenes complexity required to support the operations that would commonly be specified within inner loops .

Perhaps the most obvious is validity checking on indirect memory references — such as checking pointers for null and checking indexes against array boundaries. Most high-level languages perform these checks implicitly, but C does not. However, this is not necessarily a fundamental limitation of these other languages — a sufficiently clever comstackr may be capable of removing these checks from the inner loops of an algorithm through some form of loop-invariant code motion .

The more fundamental advantage of C (and to a similar extent the closely related C++) is a heavy reliance on stack-based memory allocation , which is inherently fast for allocation, deallocation, and access. In C (and C++) the primary call stack can be used for allocation of primitives, arrays, and aggregates ( struct / class ).

While C does offer the capability to dynamically allocate memory of arbitrary size and lifetime (using the so called ‘heap’), doing so is avoided by default (the stack is used instead).

Tantalizingly, it is sometimes possible to replicate the C memory allocation strategy within the runtime environments of other programming languages. This has been demonstrated by asm.js , which allows code written in C or C++ to be translated into a subset of JavaScript and run safely in a web browser environment — with near-native speed.


As somewhat of an aside, another area where C and C++ outshine most other languages for speed is the ability to seamlessly integrate with native machine instruction sets. A notable example of this is the (comstackr and platform dependent) availability of SIMD insortingnsics which support the construction of custom algorithms that take advantage of the now nearly ubiquitous parallel processing hardware — while still utilizing the data allocation abstractions provided by the language (lower-level register allocation is managed by the comstackr).

I have found an Answer on link about why some languages are faster and some are slower, I hope this will clear more about why C or C++ is faster than others, There are some other languages also that is faster than C, but we can not use all of them. Some explaination –

One of the big reasons that Fortran remains important is because it’s fast: number crunching routines written in Fortran tend to be quicker than equivalent routines written in most other languages. The languages that are competing with Fortran in this space—C and C++—are used because they’re competitive with this performance.

This raises the question: why? What is it about C++ and Fortran that make them fast, and why do they outperform other popular languages, such as Java or Python?

Interpreting versus compiling There are many ways to categorize and define programming languages, according to the style of programming they encourage and features they offer. When looking at performance, the biggest single distinction is between interpreted languages and comstackd ones.

The divide is not hard; rather, there’s a spectrum. At one end, we have traditional comstackd languages, a group that includes Fortran, C, and C++. In these languages, there is a discrete compilation stage that translates the source code of a program into an executable form that the processor can use.

This compilation process has several steps. The source code is analyzed and parsed. Basic coding mistakes such as typos and spelling errors can be detected at this point. The parsed code is used to generate an in-memory representation, which too can be used to detect mistakes—this time, semantic mistakes, such as calling functions that don’t exist, or trying to perform arithmetic operations on ssortingngs of text.

This in-memory representation is then used to drive a code generator, the part that produces executable code. Code optimization, to improve the performance of the generated code, is performed at various times within this process: high-level optimizations can be performed on the code representation, and lower-level optimizations are used on the output of the code generator.

Actually executing the code happens later. The entire compilation process is simply used to create something that can be executed.

At the opposite end, we have interpreters. The interpreters will include a parsing stage similar to that of the comstackr, but this is then used to drive direct execution, with the program being run immediately.

The simplest interpreter has within it executable code corresponding to the various features the language supports—so it will have functions for adding numbers, joining ssortingngs, whatever else a given language has. As it parses the code, it will look up the corresponding function and execute it. Variables created in the program will be kept in some kind of lookup table that maps their names to their data.

The most extreme example of the interpreter style is something like a batch file or shell script. In these languages, the executable code is often not even built into the interpreter itself, but rather separate, standalone programs.

So why does this make a difference to performance? In general, each layer of indirection reduces performance. For example, the fastest way to add two numbers is to have both of those numbers in registers in the processor, and to use the processor’s add instruction. That’s what comstackd programs can do; they can put variables into registers and take advantage of processor instructions. But in interpreted programs, that same addition might require two lookups in a table of variables to fetch the values to add, then calling a function to perform the addition. That function may very well use the same processor instruction as the comstackd program uses to perform the actual addition, but all the extra work before the instruction can actually be used makes things slower.

If you want to know more please check the Source

Even the difference between C and C++ can at times be great.

When you are allocating memory for an object, invoking constructors, aligning memory on word boundaries, etc. the program winds up going through a lot of overhead that is abstracted away from the programmer.

C forces you to take a look at each thing that your program is doing, generally at a very fine level of detail. This makes it harder (although not by any means impossible) to write code that does a lot of tasks that are unnecessary to the immediate goal at hand.

So where in, for instance a BASIC program you would use the INPUT keyword to read a ssortingng form STDIN and automatically allocate memory for its variable, in C the programmer will typically have already allocated memory and can control things like whether the program blocks for I/O or not, and if it stops reading input after it has the information it needs or continues reading characters to the end of the line.

C also performs a lot less error-checking than other languages, presuming the programmer knows what they’re doing. So whereas in PHP if you declare a ssortingng $myStr = getInput(); and go on to reference $myStr[20] , but the input was only 10 characters long, PHP will catch this and safely return to you a blank ssortingng. C assumes that you’ve either allocated enough memory to hold data past the end of the ssortingng or that you know what information comes after the ssortingng and are trying to reference that instead. These small factors have a huge impact on overhead in aggregate.

Just step through the machine code in your IDE, and you’ll see why it’s faster (if it’s faster). It leaves out a lot of hand-holding. Chances are your Cxx can also be told to leave it out too, in which case it should be about the same.

Comstackr optimizations are overrated, as are almost all perceptions about language speed.

Optimization of generated code only makes a difference in hotspot code, that is, tight algorithms devoid of function calls (explicit or implicit). Anywhere else, it achieves very little.