Je sais que j'ai souvent entendu dire que le langage C offre généralement un avantage en termes de performances par rapport au C ++. Je n'y ai pas vraiment pensé avant de me rendre compte que MSVC ne semble même pas prendre en charge le dernier standard de C, mais le plus récent, le C99 (à ma connaissance).
J'avais l'intention d'écrire une bibliothèque avec du code à restituer sous OpenGL afin de pouvoir la réutiliser. J'avais l'intention d'écrire la bibliothèque en C, car toute augmentation des performances est la bienvenue pour les graphiques.
Mais cela en vaut-il vraiment la peine? Le code utilisant la bibliothèque serait probablement écrit en C ++ et je préfère coder en C ++ en général.
Cependant, si cela produisait même une petite différence de performance, j'irais probablement avec C.
Il convient également de noter que cette bibliothèque serait quelque chose que je ferais pour fonctionner sous Windows / OS X / Linux et que je compilerais probablement tout en natif (MSVC pour Windows, Clang ou GCC pour OS X et GCC pour Linux. .ou éventuellement les compilateurs d’Intel pour tout).
J'ai regardé autour de moi et j'ai trouvé des points de repère et autres, mais tout ce que j'ai vu concerne GCC plutôt que MSVC et Clang. De plus, les repères ne mentionnent pas les standards des langues utilisées. Quelqu'un a un avis là dessus?
MODIFIER:Je voulais juste partager mon point de vue sur cette question après quelques années d'expérience. J'ai fini par écrire le projet pour lequel je posais cette question en C ++. J'ai commencé un autre projet à peu près au même moment en C, car nous cherchions à obtenir une petite performance. Nous avions besoin d'un lien pour le projet en C. Il y a quelques mois, j'ai atteint le point où j'avais vraiment besoin de cartes et de technologies avancées. manipulation de chaîne. Je connaissais les possibilités de cette fonctionnalité dans la bibliothèque standard C ++ et suis finalement parvenu à la conclusion que ces structures de la bibliothèque standard seraient probablement plus performantes et plus stables que les cartes et les chaînes que je pouvais implémenter en C dans un délai raisonnable. L'exigence de pouvoir être lié en C était facilement satisfaite en écrivant une interface C dans le code C ++, ce qui était fait rapidement avec des types opaques. La réécriture de la bibliothèque en C ++ semblait aller beaucoup plus vite que lors de l’écriture en C et était moins sujette aux bogues, en particulier aux fuites de mémoire. J'ai également pu utiliser la bibliothèque de threading standard de la bibliothèque, ce qui était beaucoup plus simple que d'utiliser des implémentations spécifiques à la plate-forme. En fin de compte, je pense que l’écriture de la bibliothèque en C ++ a apporté d’énormes avantages, avec éventuellement un faible coût en termes de performances. Je n'ai pas encore évalué la version C ++, mais je pense qu'il est même possible que j'aie gagné en performance en utilisant des structures de données de bibliothèque standard par rapport à celles que j'ai écrites. Je crois que l’écriture de la bibliothèque en C ++ a eu d’énormes avantages, avec éventuellement un faible coût en termes de performances. Je n'ai pas encore évalué la version C ++, mais je pense qu'il est même possible que j'aie gagné en performance en utilisant des structures de données de bibliothèque standard par rapport à celles que j'ai écrites. Je crois que l’écriture de la bibliothèque en C ++ a eu d’énormes avantages, avec éventuellement un faible coût de performances. Je n'ai pas encore évalué la version C ++, mais je pense qu'il est même possible que j'aie gagné en performance en utilisant des structures de données de bibliothèque standard par rapport à celles que j'ai écrites.
Réponses:
J'imagine que les gens prétendent souvent que le C est plus rapide que le C ++, car il est plus facile de raisonner les performances en C. C ++ n'est pas nécessairement plus lent ni plus rapide, mais certains codes C ++ peuvent masquer les inconvénients des performances cachés. Par exemple, il peut exister des copies et des conversions implicites qui ne sont pas immédiatement visibles lorsque vous consultez du code C ++.
Prenons la déclaration suivante:
Supposons en outre que
doSomething
la signature soit la suivanteEssayons maintenant d'analyser l'impact possible de cette affirmation sur les performances.
En C, les implications sont assez claires.
foo
ne peut être qu'un pointeur sur une structure etdoSomething
doit être un pointeur sur une fonction.*c
déréférence unea + 5
addition longue et entière. La seule incertitude vient du type dea
: Si ce n'est pas un int, il y aura une conversion. mais à part cela, il est facile de quantifier l'impact de cette déclaration sur la performance.Passons maintenant au C ++. La même déclaration peut maintenant avoir des caractéristiques de performance très différentes:
doSomething
pourrait être une fonction non membre virtuel (pas cher), la fonction de membre virtuel (un peu plus cher),std::function
lambda ... etc. Ce qui est pire,foo
pourrait être un type de classe surchargeoperator->
avec une opération de complexité unkown. Donc, afin de quantifier le coût des appelsdoSomething
, il est maintenant nécessaire de connaître la nature exacte defoo
etdoSomething
.a
pourrait être un entier, ou une référence à un entier (additionnel), ou un type de classe qui implémenteoperator+(int)
. L'opérateur pourrait même renvoyer un autre type de classe auquel il est implicitement convertibleint
. Encore une fois, le coût de la performance ne ressort pas de la seule déclaration.c
pourrait être une implémentation de type classeoperator*()
. Cela pourrait aussi être une référence à unlong*
etc.Vous obtenez l'image. En raison des fonctionnalités de langage C ++, il est beaucoup plus difficile de quantifier les coûts de performance d'un seul énoncé qu'en C. Maintenant, en outre, des abstractions telles que
std::vector
,std::string
sont couramment utilisées en C ++, qui ont leurs propres performances et cachent des allocations de mémoire dynamiques ( voir aussi la réponse de @ Ian).En résumé, les résultats sont les suivants: en général, il n’ya aucune différence entre les performances possibles en C ou C ++. Mais pour un code vraiment critique en termes de performances, les utilisateurs préfèrent souvent utiliser C parce qu'il existe beaucoup moins de pénalités de performances cachées .
la source
Le code écrit en C ++ peut être plus rapide qu'en C, pour certains types de tâches.
Si vous préférez C ++, utilisez C ++. Tous les problèmes de performances seront insignifiants par rapport aux décisions algorithmiques de votre logiciel.
la source
L'un des principes de conception du C ++ est que vous ne payez pas pour des fonctionnalités que vous n'utilisez pas. Ainsi, si vous écrivez du code en C ++ et évitez les fonctionnalités qui n'existent pas en C, le code compilé résultant devrait être équivalent en performances (vous devrez toutefois mesurer cela).
L'utilisation de classes, par exemple, présente un coût négligeable par rapport aux structures et à un ensemble de fonctions associées. Les fonctions virtuelles coûteront un peu plus cher, et il vous faudrait mesurer les performances pour voir si elles sont importantes pour votre application. Il en va de même pour toute autre fonctionnalité du langage C ++.
la source
this
fonctionnalité de langage de pointeur. C'est tout ce que je disais.L'une des raisons pour lesquelles les langages de niveau supérieur sont parfois plus lents est qu'ils peuvent cacher beaucoup plus de ressources cachées dans la gestion de la mémoire que les langages de niveau inférieur.
Toute langue (ou bibliothèque, API, etc.) qui fait abstraction des détails de bas niveau peut potentiellement masquer des opérations coûteuses. Par exemple, dans certaines langues, le simple fait de rogner les espaces à la fin d'une chaîne entraîne l'allocation de mémoire et une copie de la chaîne. L'allocation de mémoire et la copie en particulier peuvent coûter cher si elles se produisent de manière répétée dans une boucle serrée.
Si vous écriviez ce genre de code en C, cela serait flagrant. En C ++ peut-être moins, car les allocations et la copie pourraient être abstraites dans une classe quelque part. Ils peuvent même être cachés derrière un opérateur ou un constructeur de copie surchargé et d'apparence innocente.
Utilisez donc C ++ si vous le souhaitez. Mais ne soyez pas séduit par l'apparente commodité d'abstractions quand vous ne savez pas ce qui les cache.
Bien sûr, utilisez un profileur pour déterminer ce qui ralentit réellement votre code.
la source
Pour ce que cela vaut, j'ai tendance à écrire mes bibliothèques en C ++ 11 pour le jeu de fonctionnalités amélioré. J'aime pouvoir tirer parti de choses telles que les pointeurs partagés, les exceptions, la programmation générique et d'autres fonctionnalités uniquement en C ++. J'aime C ++ 11 car j'ai constaté qu'une bonne partie de celle-ci est prise en charge sur toutes les plateformes qui comptent pour moi. Visual Studio 2013 dispose de nombreuses fonctionnalités de langage de base et d'implémentations de bibliothèques prêtes à l'emploi et travaille apparemment à l'ajout du reste. Comme vous le savez bien, Clang et GCC prennent également en charge l'ensemble des fonctionnalités.
Cela dit, j'ai récemment entendu parler d'une stratégie vraiment géniale en matière de développement de bibliothèques qui, selon moi, est directement pertinente pour votre requête. L'article s'intitule "Un style de gestion des erreurs CA qui joue bien avec les exceptions C ++" Stefanu Du Toit appelle cette stratégie un motif "sablier". Le premier paragraphe de l'article:
Maintenant, pour répondre à votre principale préoccupation: la performance.
Comme de nombreuses autres réponses ici, je suggérerais qu'écrire du code dans l'une ou l'autre langue fonctionnerait tout aussi bien sur le plan de la performance. D'un point de vue personnel, l'écriture de code correct en C ++ est plus facile en raison des fonctionnalités du langage, mais je pense que c'est une préférence personnelle. Quoi qu'il en soit, les compilateurs sont vraiment intelligents et ont tendance à écrire de meilleurs codes que vous. Cela signifie que le compilateur optimisera probablement votre code mieux que vous ne le pourriez.
Je sais que beaucoup de programmeurs le disent, mais la première chose à faire est d’écrire votre code, puis de le profiler et d’optimiser là où votre profileur vous le suggère. Votre temps sera bien mieux utilisé pour la production de fonctionnalités, puis l'optimisation une fois que vous pourrez voir où se trouvent vos goulots d'étranglement.
Maintenant, pour quelques lectures amusantes sur la façon dont les fonctionnalités et les optimisations linguistiques peuvent vraiment jouer en votre faveur:
std :: unique_ptr a zéro overhead
constexp permet un calcul au moment de la compilation
déplacer la sémantique empêche les objets temporaires inutiles
la source
std::unique_ptr has zero overhead
Cela ne peut vraisemblablement pas être vrai (techniquement parlant) car son constructeur doit être appelé si la pile se déroule à cause d'une exception. Un pointeur brut n'a pas cette surcharge et reste correct si votre code ne sera probablement pas lancé. Un compilateur ne pourra pas le prouver dans le cas général.unique_ptr
? C'est déclarénoexcept
, et donc au moins, il gère toutes les exceptions, mais je ne peux pas imaginer quel type d'exception pourrait même être levé en premier lieu.La différence de performances entre C ++ et C n’est due à rien dans le langage à proprement parler, mais à ce que vous tentez de faire. C'est comme une carte de crédit contre de l'argent. Cela ne vous fait pas dépenser plus, mais vous le faites quand même, à moins d'être très discipliné.
Voici un exemple de programme écrit en C ++, qui a ensuite été optimisé en fonction des performances. Vous devez savoir comment ajuster les performances de manière agressive, quelle que soit la langue. La méthode que j'utilise est la pause aléatoire, comme le montre cette vidéo .
Les types de tâches coûteuses que le C ++ vous incite à faire sont la gestion de mémoire excessive, la programmation de type notification, la confiance de votre programme dans des bibliothèques d'abstraction multicouches (comme @Ian l'a dit), la dissimulation de lenteur, etc.
la source
C n’a aucun avantage en termes de performances par rapport au C ++ si vous faites la même chose dans les deux langages. Vous pouvez utiliser n'importe quel ancien code C écrit par n'importe quel programmeur décent et le transformer en code C ++ valide et équivalent, qui s'exécutera tout aussi rapidement (à moins que vous et votre compilateur sachiez ce que fait le mot clé "restrict" et que vous l'utilisez efficacement, mais la plupart des gens ne le font pas).
Les performances du C ++ peuvent être très différentes, que ce soit plus lentement ou plus rapidement, si (1) vous utilisez la bibliothèque standard C ++ pour effectuer des tâches beaucoup plus rapidement et facilement sans utiliser la bibliothèque, ou (2) si vous utilisez la bibliothèque standard C ++ faire les choses beaucoup plus facilement et rapidement que de réimplémenter la bibliothèque dans le mauvais C.
la source