Ich weiß, dass ich ziemlich oft gehört habe, dass C typischerweise einen Leistungsvorteil gegenüber C ++ hat. Ich habe nicht wirklich darüber nachgedacht, bis mir klar wurde, dass MSVC nicht einmal den neuesten Standard von C zu unterstützen scheint, aber der neueste, der es unterstützt, C99 (soweit ich weiß).
Ich hatte vor, eine Bibliothek mit Code zu schreiben, der in OpenGL gerendert werden soll, damit ich ihn wiederverwenden kann. Ich hatte vor, die Bibliothek in C zu schreiben, da jede Leistungssteigerung in Bezug auf Grafiken willkommen ist.
Aber wäre es das wirklich wert? Der Code, der die Bibliothek verwendet, wird wahrscheinlich in C ++ geschrieben, und ich bevorzuge generell den Code in C ++.
Wenn es jedoch auch nur einen kleinen Leistungsunterschied geben würde, würde ich wahrscheinlich mit C gehen.
Es kann auch angemerkt werden, dass diese Bibliothek etwas wäre, das ich für die Arbeit unter Windows / OS X / Linux machen würde, und ich würde wahrscheinlich alles nativ kompilieren (MSVC für Windows, Clang oder GCC für OS X und GCC für Linux). .oder möglicherweise Intels Compiler für alles).
Ich habe mich umgesehen und einige Benchmarks und dergleichen gefunden, aber alles, was ich gesehen habe, hat sich eher mit GCC als mit MSVC und Clang befasst. Außerdem erwähnen die Benchmarks nicht die Standards der verwendeten Sprachen. Hat jemand irgendwelche Gedanken dazu?
BEARBEITEN:Ich wollte nur nach ein paar Jahren mehr Erfahrung meinen Standpunkt zu dieser Frage teilen. Am Ende habe ich das Projekt geschrieben, für das ich diese Frage in C ++ gestellt habe. Ich habe ein anderes Projekt ungefähr zur selben Zeit in C gestartet, als wir versucht haben, eine möglichst geringe Performance zu erzielen. Vor ein paar Monaten hatte ich den Punkt erreicht, an dem ich wirklich Karten brauchte und mich weiterentwickelte String-Manipulation. Ich kannte die Fähigkeiten dafür in der C ++ - Standardbibliothek und kam schließlich zu dem Schluss, dass diese Strukturen in der Standardbibliothek wahrscheinlich besser abschneiden und stabiler sind als Maps und Strings, die ich in angemessener Zeit in C implementieren könnte. Die Anforderung, in C verlinkbar zu sein, wurde leicht erfüllt, indem eine C-Schnittstelle zum C ++ - Code geschrieben wurde, was mit undurchsichtigen Typen schnell erledigt wurde. Das Umschreiben der Bibliothek in C ++ schien viel schneller zu gehen als beim Schreiben in C und war weniger anfällig für Fehler, insbesondere für Speicherverluste. Ich konnte auch die Standardbibliotheks-Threading-Bibliothek verwenden, die viel einfacher war als die Verwendung plattformspezifischer Implementierungen. Letztendlich, glaube ich, hat das Schreiben der Bibliothek in C ++ zu großen Vorteilen bei möglicherweise geringen Leistungskosten geführt. Ich habe die C ++ - Version noch nicht verglichen, aber ich glaube, dass es sogar möglich ist, dass ich durch die Verwendung von Standard-Bibliotheksdatenstrukturen eine gewisse Leistung erzielt habe, als ich sie geschrieben habe. Ich glaube, dass das Schreiben der Bibliothek in C ++ zu großen Vorteilen bei möglicherweise geringen Leistungskosten geführt hat. Ich habe die C ++ - Version noch nicht verglichen, aber ich glaube, dass es sogar möglich ist, dass ich durch die Verwendung von Standard-Bibliotheksdatenstrukturen eine gewisse Leistung erzielt habe, als ich sie geschrieben habe. Ich glaube, dass das Schreiben der Bibliothek in C ++ zu großen Vorteilen bei möglicherweise geringen Leistungskosten geführt hat. Ich habe die C ++ - Version noch nicht verglichen, aber ich glaube, dass es sogar möglich ist, dass ich durch die Verwendung von Standard-Bibliotheksdatenstrukturen eine gewisse Leistung erzielt habe, als ich sie geschrieben habe.
Antworten:
Ich denke , die Menschen oft behaupten , dass C schneller als C ++ ist , weil es einfacher ist Grund über die Leistung in C. C ++ ist nicht von Natur aus langsamer oder schneller, aber bestimmte C ++ Code könnte versteckte Leistungseinbußen verschleiern. Beispielsweise kann es Kopien und implizite Konvertierungen geben, die bei der Betrachtung eines Teils des C ++ - Codes nicht sofort sichtbar sind.
Nehmen wir die folgende Aussage:
Nehmen wir weiter an, dass
doSomething
das folgende Signatur hat:Versuchen wir nun, die möglichen Auswirkungen dieser bestimmten Anweisung auf die Leistung zu analysieren.
In C sind die Implikationen klar.
foo
kann nur ein Zeiger auf eine Struktur sein unddoSomething
muss ein Zeiger auf eine Funktion sein.*c
dereferences a long, unda + 5
ist eine ganzzahlige Addition. Die einzige Unsicherheit ergibt sich aus der Art vona
: Wenn es sich nicht um eine Ganzzahl handelt, kommt es zu einer gewissen Konvertierung. Abgesehen davon ist es einfach, die Auswirkungen dieser einzelnen Anweisung auf die Leistung zu quantifizieren.Wechseln wir nun zu C ++. Dieselbe Aussage kann nun sehr unterschiedliche Leistungsmerkmale haben:
doSomething
könnte eine nicht-virtuelle Member - Funktion (billig), Funktion virtuelle Element (etwas teurer)std::function
, Lambda ... usw. Was noch schlimmer ist,foo
könnte ein Klassentyp Überlastung seinoperator->
mit einigem Betrieb von unkown Komplexität. Um die Anrufkosten zu quantifizierendoSomething
, ist es nun erforderlich, die genaue Art vonfoo
und zu kennendoSomething
.a
Dies kann eine Ganzzahl oder ein Verweis auf eine Ganzzahl (zusätzliche Indirektion) oder ein Klassentyp sein, der implementiert wirdoperator+(int)
. Der Operator könnte sogar einen anderen Klassentyp zurückgeben, in den implizit konvertiert werden kannint
. Wiederum sind die Leistungskosten nicht allein aus der Aussage ersichtlich.c
könnte ein Klassentyp sein, der implementiertoperator*()
. Es könnte sich auch um einen Verweis auf einlong*
usw. handeln.Du bekommst das Bild. Aufgrund C ++ 's Sprachfunktionen, ist es viel schwieriger , eine einzige Anweisung Performance Kosten zu quantifizieren , als es in C. Jetzt zusätzlich ist, Abstraktionen wie
std::vector
,std::string
sind in C häufig verwendete ++, die Leistungsmerkmale ihrer eigenen, und Speicherzuordnungen dynamisch auszublenden ( siehe auch @Ians Antwort).Das Fazit lautet also: Im Allgemeinen gibt es keinen Unterschied in der möglichen Leistung, die mit C oder C ++ erzielt werden kann. Bei wirklich leistungskritischem Code bevorzugen die Benutzer jedoch häufig die Verwendung von C, da es weitaus weniger mögliche versteckte Leistungseinbußen gibt.
quelle
In C ++ geschriebener Code kann für bestimmte Aufgabentypen schneller als in C sein.
Wenn Sie C ++ bevorzugen, verwenden Sie C ++. Leistungsprobleme sind im Vergleich zu algorithmischen Entscheidungen Ihrer Software unbedeutend.
quelle
Eines der Designprinzipien von C ++ ist, dass Sie nicht für Funktionen bezahlen, die Sie nicht nutzen. Wenn Sie also Code in C ++ schreiben und Features vermeiden, die in C nicht vorhanden sind, sollte der resultierende kompilierte Code in der Leistung gleichwertig sein (obwohl Sie dies messen müssten).
Die Verwendung von Klassen ist beispielsweise im Vergleich zu Strukturen und einer Reihe zugehöriger Funktionen mit vernachlässigbaren Kosten verbunden. Virtuelle Funktionen kosten etwas mehr und Sie müssen die Leistung messen, um festzustellen, ob sie für Ihre Anwendung von Bedeutung sind. Gleiches gilt für alle anderen C ++ - Sprachfunktionen.
quelle
this
Zeigersprachenfunktion zu verwenden. Das ist alles was ich sagte.Ein Grund dafür, dass höhere Sprachen manchmal langsamer sind, ist, dass sie sich hinter den Kulissen viel stärker als niedrigere Sprachen im Speichermanagement verstecken können.
Jede Sprache (oder Bibliothek, API usw.), die Details auf niedriger Ebene abstrahiert, kann möglicherweise kostspielige Vorgänge verbergen. In einigen Sprachen führt beispielsweise das einfache Trimmen von nachgestellten Leerzeichen aus einer Zeichenfolge zu einer Speicherzuweisung und einer Kopie der Zeichenfolge. Insbesondere die Speicherzuweisung und das Kopieren können teuer werden, wenn sie wiederholt in einer engen Schleife stattfinden.
Wenn Sie diese Art von Code in C schreiben würden, wäre dies offensichtlich. In C ++ ist dies möglicherweise weniger der Fall, da die Zuordnungen und das Kopieren irgendwo in eine Klasse abstrahiert werden könnten. Sie könnten sich sogar hinter einem unschuldig aussehenden überladenen Operator oder Kopierkonstruktor verstecken.
Verwenden Sie also C ++, wenn Sie möchten. Aber lassen Sie sich nicht von der scheinbaren Bequemlichkeit von Abstraktionen verführen, wenn Sie nicht wissen, was darunter liegt.
Verwenden Sie natürlich einen Profiler, um herauszufinden, was Ihren Code wirklich verlangsamt.
quelle
Ich neige dazu, meine Bibliotheken in C ++ 11 für den erweiterten Funktionsumfang zu schreiben. Ich mag es, Dinge wie gemeinsame Zeiger, Ausnahmen, generische Programmierung und andere reine C ++ - Funktionen zu nutzen. Ich mag C ++ 11, weil ich festgestellt habe, dass ein gutes Stück davon auf allen Plattformen unterstützt wird, die mir wichtig sind. Visual Studio 2013 verfügt über viele der wichtigsten Sprachfunktionen und Bibliotheksimplementierungen und arbeitet angeblich daran, den Rest hinzuzufügen. Wie Sie wissen, unterstützen sowohl Clang als auch GCC den gesamten Funktionsumfang.
Vor diesem Hintergrund habe ich kürzlich über eine wirklich gute Strategie in Bezug auf die Bibliotheksentwicklung gelesen, die meiner Meinung nach für Ihre Anfrage direkt relevant ist. Der Artikel trägt den Titel "AC-Fehlerbehandlungsstil, der mit C ++ - Ausnahmen gut funktioniert ". Stefanu Du Toit bezeichnet diese Strategie als "Sanduhr" -Muster. Der erste Absatz des Artikels:
Nun zu Ihrem Hauptanliegen: Leistung.
Ich würde vorschlagen, wie viele der anderen Antworten hier, dass das Schreiben von Code in beiden Sprachen unter Performance-Gesichtspunkten genauso gut funktioniert. Vom persönlichen Standpunkt aus finde ich es aufgrund der Sprachfunktionen einfacher, richtigen Code in C ++ zu schreiben, aber ich denke, das ist eine persönliche Präferenz. In beiden Fällen sind Compiler sehr schlau und schreiben normalerweise besseren Code als Sie. Das heißt, dass der Compiler Ihren Code wahrscheinlich besser optimieren wird, als Sie es könnten.
Ich weiß, dass viele Programmierer dies sagen, aber das erste, was Sie tun sollten, ist, Ihren Code zu schreiben, ihn dann zu profilieren und Optimierungen vorzunehmen, wo Ihr Profiler dies vorschlägt. Ihre Zeit wird viel besser damit verbracht, Features zu erstellen und sie dann zu optimieren, sobald Sie sehen, wo Ihre Engpässe sind.
Nun ein paar lustige Lektüren darüber, wie Sprachfunktionen und -optimierungen wirklich zu Ihren Gunsten wirken können:
std :: unique_ptr hat keinen Overhead
constexp ermöglicht die Berechnung zur Kompilierungszeit
Bewegungssemantik verhindert unnötige temporäre Objekte
quelle
std::unique_ptr has zero overhead
Dies kann (technisch gesehen) unmöglich wahr sein, da der Konstruktor aufgerufen werden muss, wenn sich der Stapel aufgrund einer Ausnahme abwickelt. Ein roher Zeiger hat diesen Overhead nicht und ist trotzdem korrekt, wenn Ihr Code wahrscheinlich nicht wirft. Ein Compiler kann dies im allgemeinen Fall nicht nachweisen.unique_ptr
? Es ist deklariertnoexcept
und behandelt daher zumindest alle Ausnahmen, aber ich kann mir nicht vorstellen, welche Art von Ausnahme überhaupt überhaupt geworfen werden könnte.Der Leistungsunterschied zwischen C ++ und C ist streng genommen nichts in der Sprache zu suchen, sondern in dem, was Sie dazu verleitet. Es ist wie eine Kreditkarte gegen Bargeld. Es bringt Sie nicht dazu, mehr auszugeben, aber Sie tun es trotzdem, es sei denn, Sie sind sehr diszipliniert.
Hier ist ein Beispiel eines in C ++ geschriebenen Programms, das dann aggressiv an der Leistung angepasst wurde. Sie müssen wissen, wie Sie eine aggressive Leistungsoptimierung durchführen, unabhängig von der Sprache. Die Methode, die ich benutze, ist zufälliges Anhalten, wie in diesem Video gezeigt .
Die kostspieligen Dinge, die C ++ zu tun versucht, sind übermäßiges Speichermanagement, Programmierung im Benachrichtigungsstil, Vertrauen in die mehrschichtigen Abstraktionsbibliotheken (wie @Ian sagte), langsames Verstecken usw.
quelle
C hat keinen Leistungsvorteil gegenüber C ++, wenn Sie in beiden Sprachen die gleichen Aktionen ausführen. Sie können jeden alten C-Code, der von einem anständigen C-Programmierer geschrieben wurde, in gültigen und äquivalenten C ++ - Code umwandeln, der genauso schnell ausgeführt wird (es sei denn, Sie und Ihr Compiler wissen, was das Schlüsselwort "restricted" bewirkt, und Sie verwenden es effektiv. aber die meisten Leute nicht).
C ++ kann eine sehr unterschiedliche Leistung aufweisen, entweder langsamer oder schneller, wenn (1) Sie die Standard-C ++ - Bibliothek verwenden, um Dinge zu erledigen, die ohne die Bibliothek viel schneller und einfacher erledigt werden können, oder (2) wenn Sie die Standard-C ++ - Bibliothek verwenden Es ist viel einfacher und schneller, als die Bibliothek in Bad C neu zu implementieren.
quelle