Warum ist C so schnell und warum sind andere Sprachen nicht so schnell oder schneller? [geschlossen]


208

Beim Anhören des StackOverflow-Podcasts taucht immer wieder auf, dass "echte Programmierer" in C schreiben und dass C so viel schneller ist, weil es "in der Nähe der Maschine" ist. Was ist das Besondere an C, das es ermöglicht, schneller als andere Sprachen zu sein, wenn man die frühere Behauptung für einen anderen Beitrag verlässt? Oder anders ausgedrückt: Was hindert andere Sprachen daran, in Binärdateien zu kompilieren, die genauso schnell wie C ausgeführt werden?


6
Können Sie auflisten, welche bestimmte Show darüber gesprochen hat? Ich würde es gerne hören.
Giovanni Galbo

2
Wirklich überrascht, wie schlecht diese Frage beantwortet wird (die meisten Antworten ignorieren die grundlegenden Unterschiede zwischen kompilierten und interpretierten Sprachen usw., ich weiß über JIT yada yada yada Bescheid) und wie viele Menschen eine Position einnehmen, um ihre Lieblingssprache zu verteidigen (FORTRAN-Jungen brauchen eine Pille nehmen).
Tim Ring

Assemblersprache nicht vergessen. Nichts ist schneller oder kompakter als zusammengebaute Exes. Assembly ist fast rein binär, daher ist es ohne Vorurteile die schnellste Sprache.
KKZiomek

3
C ist am schnellsten, weil es die Lichtgeschwindigkeit und die Relativitätstheorie ist?
Treffen Sie Taraviya

Es ist natürlich falsch, dass C die schnellste Programmiersprache ist. Keine Programmiersprache kommt der Geschwindigkeit von FORTH nahe. FORTH wird zum Auslösen von Atombomben verwendet. Es ist die Programmiersprache auf den meisten Satelliten, die Hauptprogrammiersprache in der Internationalen Raumstation sowie im CERN und am ITER. Ich habe die Geschwindigkeit zwischen Microsoft C (verschiedene Versionen) und FORTH verglichen. Gähnen zu C ...
Scoobeedo Kühle

Antworten:


200

Es gibt nicht viel Besonderes an C. Das ist einer der Gründe, warum es schnell ist.

Neuere Sprachen, die Garbage Collection , Dynamic Typing und andere Funktionen unterstützen, die es dem Programmierer erleichtern, Programme zu schreiben.

Der Haken ist, dass es zusätzlichen Verarbeitungsaufwand gibt, der die Leistung der Anwendung beeinträchtigt. C hat nichts davon, was bedeutet, dass es keinen Overhead gibt, aber das bedeutet, dass der Programmierer in der Lage sein muss, Speicher zuzuweisen und freizugeben, um Speicherlecks zu verhindern , und sich mit der statischen Typisierung von Variablen befassen muss.

Allerdings haben viele Sprachen und Plattformen wie Java (mit seiner Java Virtual Machine ) und .NET (mit seiner Common Language Runtime) im Laufe der Jahre die Leistung verbessert, mit Fortschritten wie der Just-in-Time-Kompilierung, aus der nativer Maschinencode erzeugt wird Bytecode für eine höhere Leistung.


3
Die Speicherbereinigung kann schneller sein als die manuelle Speicherverwaltung (für kurzlebige Programme und / oder viel Speicher). GC ermöglicht eine einfache und schnelle Zuweisung, und das Programm verbringt keine Zeit damit, die Zuordnung aufzuheben.
Kornel

2
C-Programme weisen Speicher im Allgemeinen nach Bedarf zu und geben ihn frei. Das ist ineffizient. Eine gute VM wird in großen Blöcken zugeordnet und freigegeben, was in vielen Fällen zu großen Leistungssteigerungen führt.
Skaffman

60
Nichts hindert ein C-Programm daran, die gleiche Zuordnung und Speicherbereinigung durchzuführen, abgesehen davon, dass es "hart" ist.
Ephemient

Sehr gut gesagt, aber wie Rob Allen sagte, bietet C auch weniger Abstraktion als Java oder .NET, was zu weniger Übersetzungen führt (was heutzutage aufgrund der Just-in-Time-Kompilierung (JIT), wie Sie sagten, weniger wahr ist)
Gab Royer

5
PorneL, manuelle Verwaltung und sinnvolle Zuordnungen übertreffen jedes GC-System bei korrekter Verwendung immer und es wird viel Aufmerksamkeit geschenkt. Sie haben absolutes Wissen über Ihre Verwendungsmuster, der GC nicht, und GC-Systeme
erhöhen den

89

Es gibt einen Kompromiss zwischen den C-Designern. Das heißt, sie haben die Entscheidung getroffen, Geschwindigkeit über Sicherheit zu stellen. C wird nicht

  • Überprüfen Sie die Array-Indexgrenzen
  • Suchen Sie nach nicht initialisierten Variablenwerten
  • Überprüfen Sie, ob Speicherlecks vorhanden sind
  • Auf Nullzeiger-Dereferenzierung prüfen

Wenn Sie in ein Array indizieren, sind in Java einige Methodenaufrufe in der virtuellen Maschine, gebundene Überprüfungen und andere Überprüfungen der Integrität erforderlich. Das ist gültig und absolut in Ordnung , weil es die Sicherheit dort erhöht, wo sie fällig ist. Aber in C werden selbst ziemlich triviale Dinge nicht in Sicherheit gebracht. Zum Beispiel benötigt C kein memcpy, um zu überprüfen, ob sich die zu kopierenden Regionen überlappen. Es ist nicht als Sprache zum Programmieren einer Big Business-Anwendung konzipiert.

Diese Entwurfsentscheidungen sind jedoch keine Fehler in der C-Sprache . Sie sind beabsichtigt, da sie es Compilern und Bibliotheksschreibern ermöglichen, jede Leistung aus dem Computer herauszuholen. Hier ist der Geist von C, wie das C Rationale- Dokument es erklärt:

C-Code kann nicht portierbar sein. Obwohl es darum ging, Programmierern die Möglichkeit zu geben, wirklich tragbare Programme zu schreiben, wollte das Komitee Programmierer nicht dazu zwingen, portabel zu schreiben, um die Verwendung von C als "High-Level-Assembler" auszuschließen: die Fähigkeit, maschinenspezifisch zu schreiben Code ist eine der Stärken von C.

Behalten Sie den Geist von C. Das Komitee hat als Hauptziel beibehalten, den traditionellen Geist von C zu bewahren. Es gibt viele Facetten des Geistes von C, aber das Wesentliche ist ein Gemeinschaftsgefühl der zugrunde liegenden Prinzipien, auf denen die C-Sprache basiert. Einige der Facetten des Geistes von C können in Phrasen wie zusammengefasst werden

  • Vertrauen Sie dem Programmierer.
  • Verhindern Sie nicht, dass der Programmierer das tut, was getan werden muss.
  • Halten Sie die Sprache klein und einfach.
  • Geben Sie nur eine Möglichkeit an, eine Operation auszuführen.
  • Machen Sie es schnell, auch wenn nicht garantiert ist, dass es tragbar ist.

Das letzte Sprichwort bedarf einer kleinen Erklärung. Das Potenzial für eine effiziente Codegenerierung ist eine der wichtigsten Stärken von C. Um sicherzustellen, dass bei einer scheinbar sehr einfachen Operation keine Codeexplosion auftritt, werden viele Operationen so definiert, wie es die Hardware des Zielcomputers tut, anstatt von eine allgemeine abstrakte Regel. Ein Beispiel für diese Bereitschaft, mit dem zu leben, was die Maschine tut, sind die Regeln, die die Erweiterung von Zeichenobjekten zur Verwendung in Ausdrücken regeln: Ob sich die Werte von Zeichenobjekten auf vorzeichenbehaftete oder vorzeichenlose Größen erweitern, hängt normalerweise davon ab, welche Byteoperation größer ist effizient auf der Zielmaschine.


51
C prüft auf Nullzeiger-Deref, indem es heftig abstürzt :-). Gelegentlich wird auch nach Array-Indizes außerhalb des Bereichs und nicht initialisierten Variablen gesucht, indem Ihre Stapelrahmen und Daten vermasselt werden. Leider werden diese zur Laufzeit überprüft.
Paxdiablo

18
Ich würde nicht sagen, dass C nicht sicher ist, was so klingt, wie Sie es andeuten. Es geht davon aus, dass Sie kein Idiot sind. Wenn Sie eine Waffe nach unten richten und sich in den Fuß schießen, wird C Sie gerne verpflichten und dies tun lassen, da davon ausgegangen wird, dass Sie schlauer sind als es ist. Das ist nicht unbedingt eine schlechte Sache.
Bob Somers

19
@ Bob: Genau. Zu sagen, dass C nicht sicher ist, weil Sie damit gefährliche Dinge tun können, ist wie zu sagen, dass ein Auto nicht sicher ist, weil Sie damit von einer Klippe fahren können. C ist so sicher wie die Person, die fährt (aber es gibt viele unsichere Fahrer da draußen).
Robert Gamble

5
Bob, Fehler wie Pufferüberläufe zu machen bedeutet nicht, dass du ein Idiot bist. Es bedeutet nur, dass du immer noch ein Mensch bist. Mir ist klar, dass C und C ++ nicht schlecht sind (ich mag sie sehr).
Johannes Schaub - litb

4
@ JohannesSchaub-litb C ist perfekt für die groß angelegte Anwendungsprogrammierung. Wenn es schwierig ist, Projekte größer als eine Hallo-Welt zu machen, dann liegt das Problem beim Programmierer, nicht bei der Sprache ...

75

Wenn Sie einen Monat damit verbringen, etwas in C zu erstellen, das in 0,05 Sekunden ausgeführt wird, und ich einen Tag damit verbringe, dasselbe in Java zu schreiben, und es in 0,10 Sekunden ausgeführt wird, ist C dann wirklich schneller?

Um Ihre Frage zu beantworten, läuft gut geschriebener C-Code im Allgemeinen schneller als gut geschriebener Code in anderen Sprachen, da ein Teil des Schreibens von C-Code "gut" manuelle Optimierungen auf maschinennaher Ebene umfasst.

Obwohl Compiler in der Tat sehr clever sind, sind sie noch nicht in der Lage, kreativ Code zu entwickeln, der mit handmassierten Algorithmen konkurriert (vorausgesetzt, die "Hände" gehören einem guten C-Programmierer).

Bearbeiten:

Viele Kommentare lauten wie folgt: "Ich schreibe in C und denke nicht über Optimierungen nach."

Aber um ein konkretes Beispiel aus diesem Beitrag zu nehmen :

In Delphi könnte ich folgendes schreiben:

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
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;

und in CI schreiben Sie dies:

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
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 */
   }
}

Aber wie viele Optimierungen gibt es in der C-Version? Wir treffen viele Entscheidungen über die Implementierung, an die ich in der Delphi-Version nicht denke. Wie wird ein String implementiert? In Delphi sehe ich es nicht. In C habe ich beschlossen, dass es ein Zeiger auf ein Array von ASCII-Ganzzahlen sein wird, die wir Zeichen nennen. In C testen wir nacheinander die Existenz von Charakteren. In Delphi benutze ich Pos.

Und das ist nur ein kleines Beispiel. In einem großen Programm muss ein C-Programmierer diese Art von Entscheidungen auf niedriger Ebene alle paar Codezeilen treffen. Es ergibt eine handgefertigte, handoptimierte ausführbare Datei.


45
Um fair zu sein, gibt es in C nicht viel, was einen Monat dauern würde, was in Java nur einen Tag dauern würde, dessen Ausführung nur 0,05 Sekunden dauert (dh ein kleines Programm).
Dreamlax

12
Ich habe jahrelang in C programmiert und muss fast nie eine der Optimierungen vornehmen, auf die Sie hinweisen. Ich habe eine Reihe von Programmen nach C portiert (hauptsächlich von Perl) und sehe im Allgemeinen eine 10-fache Geschwindigkeitssteigerung und eine signifikante Reduzierung der Speichernutzung ohne handcodierte Optimierungen.
Robert Gamble

1
Natürlich gibt es einige Dinge, deren Programmierung in C aufgrund fehlender vorhandener Einrichtungen erheblich länger dauern kann. Daher ist dies ein Kompromiss zwischen Computerleistung und Programmiererleistung (unter anderem), weshalb wir nicht alle alles in C programmieren.
Robert Gamble

4
Ich habe C ++ - Programme erstellt, die Tausende von Datenzeilen in kürzerer Zeit verarbeiten, als Java- oder .NET-Programme gestartet werden können. Es ist eine der Frustrationen, die ich mit den moderneren Sprachen habe. C eignet sich hervorragend für Lean-Programme, für die nur minimale Laufzeitanforderungen erforderlich sind. PowerBasic ist auch dafür großartig.
Bruceatk

35
Sie sagen, ein Programm, das in C einen Monat dauert und doppelt so schnell ist wie ein in Java geschriebenes Programm, dessen Schreiben nur einen Tag dauert, lohnt sich nicht? Was ist, wenn dieses Programm mehr als 500.000.000 Mal am Tag ausgeführt werden muss? Doppelt so schnell zu sein ist unglaublich wichtig. Wenn es auf Tausenden oder Millionen von CPUs läuft, sind die Kosteneinsparungen des zusätzlichen Entwicklungsmonats, um die doppelte Leistung zu erzielen, enorm. Grundsätzlich müssen Sie den Umfang Ihrer Bereitstellung kennen / verstehen, bevor Sie sich für die Entwicklungsplattform entscheiden.
Nicerobot

49

Ich habe es noch nicht gesehen, also sage ich es: C ist tendenziell schneller, weil fast alles andere in C geschrieben ist .

Java basiert auf C, Python basiert auf C (oder Java oder .NET usw.), Perl usw. Das Betriebssystem ist in C geschrieben, die virtuellen Maschinen sind in C geschrieben, die Compiler sind in C geschrieben. Die Dolmetscher sind in C geschrieben. Einige Dinge sind immer noch in Assemblersprache geschrieben, was tendenziell noch schneller ist. Immer mehr Dinge werden in etwas anderem geschrieben, das selbst in C geschrieben ist.

Jede Anweisung, die Sie in anderen Sprachen schreiben (nicht in Assembly), wird normalerweise darunter als mehrere Anweisungen in C implementiert, die bis zum nativen Maschinencode kompiliert werden. Da diese anderen Sprachen in der Regel vorhanden sind, um einen höheren Abstraktionsgrad als C zu erzielen, konzentrieren sich die in C erforderlichen zusätzlichen Anweisungen in der Regel auf die Erhöhung der Sicherheit, die Erhöhung der Komplexität und die Bereitstellung der Fehlerbehandlung. Das sind oft gute Dinge, aber sie haben Kosten und ihre Namen sind Geschwindigkeit und Größe .

Persönlich habe ich in buchstäblich Dutzenden von Sprachen geschrieben, die den größten Teil des verfügbaren Spektrums abdecken, und ich persönlich habe die Magie gesucht, auf die Sie hinweisen:

Wie kann ich meinen Kuchen haben und ihn auch essen? Wie kann ich mit Abstraktionen auf hoher Ebene in meiner Lieblingssprache spielen und dann aus Gründen der Geschwindigkeit auf das Wesentliche von C zurückgreifen?

Nach ein paar Jahren Recherche lautet meine Antwort Python (auf C). Vielleicht möchten Sie es sich ansehen. Übrigens können Sie auch von Python aus zu Assembly wechseln (mit geringfügiger Hilfe einer speziellen Bibliothek).

Andererseits kann schlechter Code in jeder Sprache geschrieben werden . Daher ist der C- (oder Assembly-) Code nicht automatisch schneller. Ebenso können einige Optimierungstricks Teile des übergeordneten Sprachcodes nahe an das Leistungsniveau von Raw C bringen. Bei den meisten Anwendungen verbringt Ihr Programm jedoch die meiste Zeit damit, auf Personen oder Hardware zu warten, sodass der Unterschied wirklich keine Rolle spielt.

Genießen.


10
Dies gilt nicht wirklich für JIT-kompilierte Sprachen. Es ist nicht so, dass mein C # in IL kompiliert wird, das in C übersetzt wird, das in Maschinencode kompiliert wird. Nein, die IL ist JIT-kompiliert - und die Implementierungssprache der JIT ist zu diesem Zeitpunkt irrelevant. Es wird nur Maschinencode erzeugt.
Jon Skeet

3
Gott bewahre, dass ich den legendären Jon Skeet in Frage stellen sollte, aber es scheint völlig relevant zu sein, dass der erzeugte Maschinencode für C # anstelle von C ist, also "höher", mehr Funktionalität, Sicherheitsüberprüfungen usw. und Willen daher langsamer sein als das "Äquivalent" C.
Rob Williams

3
@ Jon: Ich wollte gerade etwas Ähnliches sagen, aber der Punkt ist tatsächlich etwas gültig, da viele der Kernkomponenten der .NET-Bibliothek tatsächlich in C geschrieben sind und daher die Geschwindigkeitsbeschränkungen von C aufweisen. Es wird interessant sein zu sehen, wie sich dies in Zukunft ändern wird.
Konrad Rudolph

1
Dies scheint falsch herum zu sein. Andere Sprachcompiler / Interpreter / VMs werden häufig, aber nicht immer in c (oder zumindest für die unterste Ebene) geschrieben, da c ziemlich schnell (und in vielen Fällen am schnellsten) ist.
Roman A. Taycher

2
Diese Antwort ist nicht wahr. Wie oben erwähnt, gilt dies nicht für JIT-Sprachen, aber auch nicht für Sprachen mit eigenen Compilern (die bei außerordentlichem Aufwand schnelleren Code generieren könnten als moderne C-Compiler). Die einzige andere Klasse von Sprachen, die noch übrig ist, sind interpretierte Sprachen, und diese sind nicht langsamer als C, nur weil sie selbst in C geschrieben sind, sondern weil der Aufwand für das Dolmetschen, egal wie Sie es in Scheiben schneiden und selbst wenn der Interpreter in Assembler geschrieben wurde , ist riesig.
Score_Under

38

Es gibt viele Fragen - meistens solche, für deren Beantwortung ich nicht qualifiziert bin. Aber für diesen letzten:

Was hindert andere Sprachen daran, in Binärdateien zu kompilieren, die genauso schnell wie C ausgeführt werden?

Mit einem Wort: Abstraktion.

C ist nur eine oder zwei Abstraktionsebenen von der Maschinensprache entfernt. Java und die .NET-Sprachen befinden sich mindestens drei Abstraktionsebenen vom Assembler entfernt. Bei Python und Ruby bin ich mir nicht sicher.

Je mehr Programmierspielzeug (komplexe Datentypen usw.) vorhanden ist, desto weiter sind Sie von der Maschinensprache entfernt und desto mehr Übersetzungen müssen durchgeführt werden.

Ich bin hier und da weg, aber das ist das Wesentliche.

Update ------- Es gibt einige gute Kommentare zu diesem Beitrag mit mehr Details.


3
Technisch gesehen sind Java und .Net unendlich weit von der Maschinensprache der Maschine entfernt, auf der sie ausgeführt werden. Sie laufen in VMs. Selbst mit JIT muss der ursprüngliche Code massiv massiert werden, um etwas zu erhalten, das dem nativen Maschinencode ähnelt.
jmucchiello

1
.net-Code wird in einer VM nicht ausgeführt. Es wird als native Anweisung auf jeder Prozessorplattform ausgeführt, auf der es ausgeführt wird (32-Bit x86, 64-Bit x86 oder IA64).
Robert C. Barth

11
@ Robert: .net hat eine VM verwenden. .net-Code wird in Bytecode kompiliert, der von der VM ausgeführt wird. Die VM konvertiert den Bytecode zur Laufzeit in native Anweisungen.
Robert Gamble

3
Es ist sehr wichtig zu beachten, dass Java- und andere OO-Sprachabstraktionen die Prozessoranweisungssätze beeinflusst haben. Neuere Prozessoren verfügen über Anweisungen, mit denen Java schneller ausgeführt wird, wenn die Java-VM diese Optimierungen kennt und verwendet. Es ist nicht riesig, aber es ist hilfreich.
Adam Davis


35

Es ist nicht so sehr, dass C schnell ist, sondern dass das Kostenmodell von C transparent ist . Wenn ein C-Programm langsam ist, ist es auf offensichtliche Weise langsam: durch Ausführen vieler Anweisungen. Verglichen mit den Betriebskosten in C können Operationen auf hoher Ebene an Objekten (insbesondere Reflexion) oder Zeichenfolgen Kosten verursachen, die nicht offensichtlich sind.

Zwei Sprachen, die im Allgemeinen zu Binärdateien kompiliert werden, die genauso schnell wie C sind, sind Standard ML (mit dem MLton- Compiler) und Objective Caml . Wenn Sie sich das Benchmark-Spiel ansehen, werden Sie feststellen, dass die OCaml-Version für einige Benchmarks, wie z. B. Binärbäume, schneller als C ist. (Ich habe keine MLton-Einträge gefunden.) Aber nehmen Sie das Shootout nicht zu ernst. Es ist, wie es heißt, ein Spiel. Die Ergebnisse spiegeln oft wider, wie viel Aufwand die Leute in die Optimierung des Codes gesteckt haben.


Es ist möglich, nicht offensichtlich teuren Code in jeder Sprache zu schreiben. Es ist nur so, dass man in einigen Sprachen zuerst eine innere Variante von Lisp oder Forth schreiben muss…
Donal Fellows

Auch Rust entspricht C in den Benchmarks.
splitter

18

C ist nicht immer schneller.

C ist langsamer als zum Beispiel Modern Fortran.

C ist für einige Dinge oft langsamer als Java. (Besonders nachdem der JIT-Compiler Ihren Code ausprobiert hat)

C lässt Zeiger-Aliasing zu, was bedeutet, dass einige gute Optimierungen nicht möglich sind. Insbesondere wenn Sie mehrere Ausführungseinheiten haben, führt dies zu Datenabrufstillständen. Ow.

Die Annahme, dass Zeigerarithmetik funktioniert, führt bei einigen CPU-Familien (insbesondere PIC!) Zu einer langsam aufgeblähten Leistung. Früher wurde die große Leistung bei segmentiertem x86 verwendet.

Grundsätzlich stinkt C, wenn Sie eine Vektoreinheit oder einen Parallelisierungscompiler erhalten, und das moderne Fortran läuft schneller.

C-Programmierer-Tricks wie Thunking (Ändern der ausführbaren Datei im laufenden Betrieb) führen zum Stillstand des CPU-Prefetch.

Verstehst du den Drift?

Und unser guter Freund, der x86, führt einen Befehlssatz aus, der heutzutage wenig mit der tatsächlichen CPU-Architektur zu tun hat. Schattenregister, Load-Store-Optimierer, alles in der CPU. C ist also nahe am virtuellen Metall. Das echte Metall, Intel lässt dich nicht sehen. (Historisch gesehen waren VLIW-CPUs ein bisschen pleite, vielleicht ist das gar nicht so schlecht.)

Wenn Sie in C auf einem Hochleistungs-DSP (möglicherweise einem TI-DSP?) Programmieren, muss der Compiler einige knifflige Aufgaben ausführen, um das C über mehrere parallele Ausführungseinheiten hinweg abzuwickeln. In diesem Fall befindet sich C nicht in der Nähe des Metalls, sondern in der Nähe des Compilers, wodurch die gesamte Programmoptimierung durchgeführt wird. Seltsam.

Und schließlich führen einige CPUs (www.ajile.com) Java-Bytecodes in der Hardware aus. C würde eine PITA auf dieser CPU verwenden.


1
Wann wurde das letzte Mal Thunking in C geschrieben? Modernes x86 ist eine Schnittstelle zu einem meist RISC-Design, aber das hat wenig mit VLIW zu tun ...
Calyth

7
Ein Großteil Ihres Beitrags ignoriert die Existenz von C99. Außerdem bieten viele C / C ++ - Compiler das Schlüsselwort C99 Restrict (stellt kein Zeiger-Aliasing sicher) als Erweiterung an.
Evan Teran

Ich gehe davon aus, dass jeder den CWE / SANS Top 25 folgt / übergeht und es vermeidet, neue Designs in C zu erstellen. Also keine grünen Felder C, so wenig bis gar kein C99.
Tim Williscroft

2
Können Sie ein Beispiel zeigen, wenn c langsamer als das moderne Fortenberry ist?
Adam

Ich bin mir nicht sicher, ob es jemals eine Zeit gegeben hat, in der C-Compiler sehr gut mit den besten Fortran-Compilern konkurrierten. Natürlich gibt es eine Menge Code, den Sie nicht in FORTRAN 77 schreiben möchten (geschweige denn 66), aber neuere Fortran-Standards wurden immer angenehmer.
tfb

11

Was hindert andere Sprachen daran, in Binärdateien zu kompilieren, die genauso schnell wie C ausgeführt werden?

Nichts. Moderne Sprachen wie Java oder .NET langs orientieren sich eher an der Produktivität der Programmierer als an der Leistung. Hardware ist heutzutage billig. Auch das Kompilieren zur Zwischendarstellung bietet viele Vorteile wie Sicherheit, Portabilität usw. .NET CLR kann unterschiedliche Hardware nutzen - zum Beispiel müssen Sie das Programm nicht manuell optimieren / neu kompilieren, um den SSE-Befehlssatz zu verwenden.


Ich würde die Portabilität hier argumentieren. Wenn Sie wirklich portablen Code möchten, schreiben Sie ihn in C und nicht in einer anderen Sprache. Wir haben einen Code, der auf ungefähr 25 Betriebssystemen läuft. Ausgehend von dos und threadX und unter Linux / XP zeigt mir eine andere Sprache, die das kann :)
Ilya

1
@ Ilya Ich bin anderer Meinung. Es ist genauso einfach, nicht portablen Code in C zu schreiben. Sehen Sie, wie schmerzhaft es für einige war, auf 64-Bit zu portieren. Bytecode-Sprachen können plattformübergreifend funktionieren, wenn Sie den richtigen Bytecode-Interpreter haben.
Calyth

1
@IIya, tragbarer C-Code ist eher eine Ausnahme als eine Regel. Ich habe C-Code zwischen verschiedenen Hardware- / Software-Plattformen portiert und weiß, dass es ein Albtraum ist.
Aku

Selbst für PC-Wörter ist dies nicht der Fall. Schauen Sie sich die meisten plattformübergreifenden Anwendungen an, die in c / c ++ geschrieben sind, ein wenig in Java. Für die eingebettete Low-Level-Entwicklung gibt es einfach keine anderen Fälle. C ist de facto die portabelste Sprache.
Ilya

@aku -> PORTING schlechter Code könnte eine Katastrophe sein, stimme ich zu. Das Schreiben von tragbarem Code in ADVANCE - C ist die beste Wahl. Ich würde sagen, C ++ ist eine Option, aber wenn Sie zur eingebetteten Plattform gehen, werden Sie immer einen anständigen C-Compiler finden. Für C ++ finden Sie sich möglicherweise selbst ohne Compiler.
Ilya

8

Die Hauptfaktoren sind, dass es sich um eine statisch typisierte Sprache handelt, die zu Maschinencode kompiliert wurde. Da es sich um eine einfache Sprache handelt, macht sie im Allgemeinen nichts, was Sie nicht sagen.

Dies sind einige andere Faktoren, die mir in den Sinn kommen.

  • Variablen werden nicht automatisch initialisiert
  • Keine Begrenzung der Überprüfung von Arrays
  • Deaktivierte Zeigermanipulation
  • Keine Ganzzahlüberlaufprüfung
  • Statisch typisierte Variablen
  • Funktionsaufrufe sind statisch (es sei denn, Sie verwenden Funktionszeiger).
  • Compiler-Autoren hatten viel Zeit, um den Optimierungscode zu verbessern. Außerdem wird in C programmiert, um die beste Leistung zu erzielen. Daher besteht der Druck, den Code zu optimieren.
  • Teile der Sprachspezifikation sind implementierungsdefiniert, sodass Compiler die Möglichkeit haben, die Dinge optimal zu erledigen

Die meisten statisch typisierten Sprachen könnten jedoch genauso schnell oder schneller als C kompiliert werden, insbesondere wenn sie Annahmen treffen können, die C aufgrund von Zeiger-Aliasing usw. nicht kann.


C Low-Level? Ich denke, es ist jetzt eine relative Bedeutung, verglichen mit Java ja, aber verglichen mit Assembly nein. Guter Beitrag, hat mich zum Nachdenken gebracht.
Mark

Du hast recht, es ist definitiv relativ. Was ich damit meine ist, dass es "in der Nähe der Maschine" ist und Ihnen nicht hilft, Dinge wie Speicherverwaltung oder das Verfolgen von Array-Größen zu tun.
Matthew Crumley

2
C ist eine einfache Sprache. C war schon immer eine einfache Sprache. Sie übersetzen C-Code ohne große Schwierigkeiten von Hand in den Assembler.
Robert C. Barth

2
@Robert: C galt früher als Hochsprache, weil es im Vergleich zu Assembler (was sehr häufig war) war. Es wird im Vergleich zu den meisten heute verwendeten Sprachen als einfache Sprache angesehen.
Robert Gamble

Ehrlich gesagt ist dies eine sehr voreingenommene Antwort. Verdammt nahe an allen C-Programmierern, die Grenzen überprüfen usw. Trotzdem ist C immer noch VIEL schneller als C ++.
MarcusJ

8

Ich denke du hast vergessen, dass Assemblersprache auch eine Sprache ist :)

Aber im Ernst, C-Programme sind nur dann schneller, wenn der Programmierer weiß, was er tut. Sie können problemlos ein C-Programm schreiben, das langsamer ausgeführt wird als Programme, die in anderen Sprachen geschrieben wurden und denselben Job ausführen.

Der Grund, warum C schneller ist, liegt darin, dass es auf diese Weise entworfen wurde. Sie können damit viele "untergeordnete" Aufgaben ausführen, die dem Compiler helfen, den Code zu optimieren. Oder, sagen wir, Sie als Programmierer sind für die Optimierung des Codes verantwortlich. Aber es ist oft ziemlich knifflig und fehleranfällig.

Andere Sprachen, wie bereits andere, konzentrieren sich mehr auf die Produktivität des Programmierers. Es wird allgemein angenommen, dass die Programmierzeit viel teurer ist als die Maschinenzeit (selbst in den alten Tagen). Daher ist es sehr sinnvoll, die Zeit, die Programmierer für das Schreiben und Debuggen von Programmen aufwenden, anstelle der Laufzeit der Programme zu minimieren. Um dies zu tun, werden Sie ein wenig dafür opfern, was Sie tun können, um das Programm schneller zu machen, da viele Dinge automatisiert sind.


3
Wenn Sie ein Programm einmal in C und erneut in Assembly geschrieben haben, ist die C-Version wahrscheinlich schneller, da der Compiler intelligenter ist als Sie.
mk12

7

Zum größten Teil entspricht jeder C-Befehl nur sehr wenigen Assembler-Befehlen. Sie schreiben im Wesentlichen Maschinencode auf höherer Ebene, sodass Sie die Kontrolle über fast alles haben, was der Prozessor tut. Viele andere kompilierte Sprachen, wie z. B. C ++, enthalten viele einfach aussehende Anweisungen, die sich in viel mehr Code verwandeln können als Sie denken (virtuelle Funktionen, Kopierkonstruktoren usw.). Und interpretierte Sprachen wie Java oder Ruby haben eine andere Ebene Anweisungen, die Sie nie sehen - die virtuelle Maschine oder der Interpreter.


Und einige dieser Hochsprachen sind stolz darauf, dass sie den größten Teil der Kruft, die sie ursprünglich hinzugefügt haben, entfernen können. Dinge wie Kopierelision, Rückgabewertoptimierung, Verschiebungskonstruktion / -zuweisung usw. in C ++.
cmaster

Es kommt also auf die Anzahl der aus dem Code generierten Montageanweisungen an. Es gibt mehr Montageanweisungen pro Zeile Code auf hoher Ebene, je mehr die Leistung leidet?
ENDEESA

Das mag zu einfach sein, aber es besteht ein direkter Zusammenhang zwischen der Anzahl der Montageanweisungen und der Programmgeschwindigkeit. Der Prozessor hat eine Mindestzeit, um jeden Befehl auszuführen. IMHO, eine Sprache, mit der Sie leicht verstehen können, wie viele Anweisungen Sie schreiben, hilft Ihnen, effizienteren Code zu schreiben. (Es gibt andere Prozessorzeitkosten wie Verzweigungs- und Cache-Fehler, aber selbst dort hilft weniger Abstraktion, klar zu machen, was die CPU tut).
AShelly


7

C ++ ist im Durchschnitt schneller (wie ursprünglich eine Obermenge von C, obwohl es einige Unterschiede gibt). Für bestimmte Benchmarks gibt es jedoch häufig eine andere Sprache, die schneller ist.

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

fannjuch-redux war am schnellsten in Scala

n-bodyund fastawaren schneller in Ada.

spectral-norm war am schnellsten in Fortran.

reverse-complement, mandelbrotUnd pidigitswaren am schnellsten in ATS.

regex-dna war am schnellsten in JavaScript.

chameneou-redux Am schnellsten war Java 7.

thread-ring war am schnellsten in Haskell.

Die restlichen Benchmarks waren in C oder C ++ am schnellsten.


"da es sich um eine Supermenge von C handelt" - Nein, C ++ ist keine Obermenge von C.
PP

1
extern "C"hat nichts damit zu tun, dass C ++ eine Obermenge von C. ist
PP

2
Es ist, als würde man sagen, dass es system("bash script.sh");für jedes Bash-Skript funktioniert, und daher ist C eine Obermenge von Bash. extern "C"stellt die C-Verknüpfung in C ++ aufgrund von Namensmangel bereit. Während das Aufrufen von X als Obermenge von Y bedeutet, dass alles, was in Y ausgeführt werden kann, auch in X ausgeführt werden kann, was für C ++ nicht gilt. Es gibt einige Sprachkonstrukte, die in C gültig sind, aber nicht in C ++.
PP

1
@PP Der C ++ - Standard enthält nichts, bashwas ein verfügbares Befehlszeilenprogramm vorschreibt . Wenn dies der Fall wäre und enthalten würde, welche Version / Spezifikation von Bash unterstützt werden muss, würde ich es als Obermenge betrachten.
Peter Lawrey

1
Es ist trivial einfach, C-Code zu schreiben, der kein C ++ - Code ist, z. B.struct foo { int: this; }; typedef float foo;
Jasen

6

Viele dieser Antworten geben gültige Gründe dafür an, warum C schneller ist oder nicht (entweder im Allgemeinen oder in bestimmten Szenarien). Es ist nicht zu leugnen, dass:

  • Viele andere Sprachen bieten automatische Funktionen, die wir für selbstverständlich halten. Die Überprüfung von Grenzen, die Überprüfung des Laufzeit-Typs und die automatische Speicherverwaltung sind beispielsweise nicht kostenlos. Mit diesen Funktionen sind zumindest einige Kosten verbunden, die wir beim Schreiben von Code, der diese Funktionen verwendet, möglicherweise nicht berücksichtigen oder gar nicht realisieren.
  • Der Schritt von der Quelle zur Maschine ist in anderen Sprachen oft nicht so direkt wie in C.
  • OTOH, zu sagen, dass kompilierter C-Code schneller ausgeführt wird als anderer in anderen Sprachen geschriebener Code, ist eine Verallgemeinerung, die nicht immer wahr ist. Gegenbeispiele sind leicht zu finden (oder zu erfinden).

Ungeachtet dessen ist mir noch etwas anderes aufgefallen, das meiner Meinung nach die Vergleichsleistung von C im Vergleich zu vielen anderen Sprachen stärker beeinflusst als jeder andere Faktor. Nämlich:

Andere Sprachen erleichtern häufig das Schreiben von Code, der langsamer ausgeführt wird. Oft wird es sogar durch die Designphilosophien der Sprache gefördert. Folgerung: Ein C-Programmierer schreibt eher Code, der keine unnötigen Operationen ausführt.

Stellen Sie sich als Beispiel ein einfaches Windows-Programm vor, in dem ein einzelnes Hauptfenster erstellt wird. Die AC-Version würde eine WNDCLASS[EX]Struktur füllen, an die übergeben würde RegisterClass[Ex], dann aufrufen CreateWindow[Ex]und eine Nachrichtenschleife eingeben. Es folgt ein stark vereinfachter und abgekürzter Code:

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);
}

Ein äquivalentes Programm in C # kann nur eine Codezeile sein:

Application.Run(new Form());

Diese eine Codezeile bietet alle Funktionen, die fast 20 Zeilen C-Code bieten, und fügt einige Dinge hinzu, die wir ausgelassen haben, z. B. die Fehlerprüfung. Die reichhaltigere, umfassendere Bibliothek (im Vergleich zu den in einem typischen C-Projekt verwendeten) hat viel Arbeit für uns geleistet und uns Zeit gelassen, viel mehr Codefragmente zu schreiben, die für uns kurz aussehen, aber viele Schritte hinter die Kulissen beinhalten.

Aber eine umfangreiche Bibliothek, die einfaches und schnelles Aufblähen von Code ermöglicht, ist nicht wirklich mein Punkt. Mein Punkt wird deutlicher, wenn Sie untersuchen, was tatsächlich passiert, wenn unser kleiner Einzeiler tatsächlich ausgeführt wird. Aktivieren Sie zum Spaß manchmal den .NET -Quellzugriff in Visual Studio 2008 oder höher und gehen Sie in die einfache einzeilige Zeile oben. Eines der lustigen kleinen Juwelen, auf das Sie stoßen werden, ist dieser Kommentar im Getter für 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(); 
} 

Zehnmal . Die Information entspricht in etwa der Summe dessen , was in einer gespeichert ist WNDCLASSEXStruktur und was übergeben wird CreateWindowExvon den abgerufen ControlKlasse zehnmal , bevor es in einer gespeichert ist WNDCLASSEXStruktur und an RegisterClassExund CreateWindowEx.

Alles in allem beträgt die Anzahl der Befehle, die zur Ausführung dieser sehr grundlegenden Aufgabe ausgeführt werden, in C # 2–3 Größenordnungen mehr als in C. Ein Teil davon ist auf die Verwendung einer funktionsreichen Bibliothek zurückzuführen, die notwendigerweise verallgemeinert ist unser einfacher C-Code, der genau das tut, was wir brauchen und nichts weiter. Ein Teil davon ist jedoch auf die Tatsache zurückzuführen, dass sich die modularisierte, objektorientierte Natur von .NET Framework für viele Wiederholungen der Ausführung eignet, die häufig durch einen prozeduralen Ansatz vermieden werden.

Ich versuche nicht, C # oder das .NET-Framework auszuwählen. Ich sage auch nicht, dass Modularisierung, Generalisierung, Bibliotheks- / Sprachfunktionen, OOP usw. schlechte Dinge sind . Ich habe den größten Teil meiner Entwicklung in C, später in C ++ und zuletzt in C # durchgeführt. In ähnlicher Weise habe ich vor C hauptsächlich Montage verwendet. Und mit jedem Schritt "höher" meiner Sprache schreibe ich bessere, wartbarere und robustere Programme in kürzerer Zeit. Sie neigen jedoch dazu, etwas langsamer auszuführen.


2
Dies ist ein API-Problem, kein Sprachproblem.
Arafangion

1
@Arafangion: Ich verstehe, was du sagst, aber es geht irgendwie am Punkt vorbei. Die funktionsreiche Bibliothek wird von der funktionsreichen Sprache aktiviert (und in gewisser Weise gefordert). Und es ist nicht nur die Bibliothek. Die Bibliothek ist nur ein Beispiel für die allgemeine Verwendung der Sprache. Typischer Anwendungscode in einer beliebigen Sprache ähnelt im Allgemeinen den in dieser Sprache normalerweise verwendeten Bibliotheken. Es ist wirklich eher eine Denkweise, die von der Sprache gefördert wird. Beispielsweise verbringen OO-Sprachen im Allgemeinen mehr Zeit mit dem Zuweisen, Erstellen, Zerstören und Freigeben von Objekten als Sprachen mit weniger OOP-Unterstützung.
P Daddy

Ich gebe zu, dass eine bestimmte Wahl der Sprache im Allgemeinen eine bestimmte Plattform und Bibliothek impliziert, weshalb ich diesen Kommentar abgegeben habe (damit der Leser besser darauf aufmerksam wird), aber das heißt, die Verwendung von (zum Beispiel) C ++ unter Windows ist a ganz anderes Biest als zum Beispiel C ++ unter Linux und wieder anders mit C ++ unter Android. Ein weiteres Beispiel ist Python - wir haben CPython, Jython, PyPy und IronPython - die alle sehr unterschiedliche Bibliotheken verwenden.
Arafangion

Mit einem dieser Pythons neigen Entwickler jedoch dazu, Anwendungen auf eine bestimmte Weise zu schreiben. Beispielsweise können sie aus einer Textdatei lesen und schreiben und mit den gelesenen Daten neue Objekte erstellen. In C hingegen würde ein Entwickler eher eine einmalige Zuweisung eines Arrays von Strukturen vornehmen und diese Strukturen aus einer Binärdatei lesen und schreiben. Dies ist natürlich nur ein erfundenes Beispiel, das versucht, den Punkt zu veranschaulichen, den ich über die Denkweise ansprechen möchte .
P Daddy

6

Ich glaube nicht, dass irgendjemand die Tatsache erwähnt hat, dass C-Compiler viel mehr Aufwand betrieben haben als jeder andere Compiler, vielleicht mit Ausnahme von Java.

C ist aus vielen der bereits genannten Gründe äußerst optimierbar - mehr als fast jede andere Sprache. Wenn also andere Sprachcompiler den gleichen Aufwand betreiben, wird C wahrscheinlich immer noch die Nase vorn haben.

Ich denke, es gibt mindestens eine Kandidatensprache, die mit Aufwand besser optimiert werden könnte als C, und daher könnten wir Implementierungen sehen, die schnellere Binärdateien erzeugen. Ich denke an Digital Mars D, weil der Ersteller darauf geachtet hat, eine Sprache zu erstellen, die möglicherweise besser optimiert werden kann als C. Möglicherweise gibt es andere Sprachen, die diese Möglichkeit haben. Ich kann mir jedoch nicht vorstellen, dass eine Sprache Compiler mehr als nur ein paar Prozent schneller haben wird als die besten C-Compiler. Ich würde gerne falsch liegen.

Ich denke, die wirkliche "niedrig hängende Frucht" wird in Sprachen sein, die so gestaltet sind, dass sie für den Menschen EINFACH zu optimieren sind. Ein erfahrener Programmierer kann jede Sprache schneller machen - aber manchmal muss man lächerliche Dinge tun oder unnatürliche Konstrukte verwenden, um dies zu erreichen. Obwohl es immer mühsam sein wird, sollte eine gute Sprache relativ schnellen Code produzieren, ohne genau darüber nachdenken zu müssen, wie das Programm geschrieben ist.

Es ist auch wichtig (zumindest für mich), dass der Worst-Case-Code in der Regel schnell ist. Es gibt zahlreiche "Beweise" im Web, dass Java genauso schnell oder schneller als C ist, aber das basiert auf Beispielen für die Kirschernte. Ich bin kein großer Fan von C, aber ich weiß, dass ALLES, was ich in C schreibe, gut laufen wird. Mit Java wird es "wahrscheinlich" innerhalb von 15% der Geschwindigkeit laufen, normalerweise innerhalb von 25%, aber in einigen Fällen kann es weitaus schlimmer sein. Alle Fälle, in denen es genauso schnell oder innerhalb von ein paar Prozent ist, sind normalerweise darauf zurückzuführen, dass die meiste Zeit im Bibliothekscode verbracht wird, der ohnehin stark optimiert ist.


5

Dies ist eigentlich eine Art fortgesetzte Lüge. Zwar sind C-Programme häufig schneller, dies ist jedoch nicht immer der Fall, insbesondere wenn der C-Programmierer nicht sehr gut darin ist.

Ein großes Loch, das die Leute gerne vergessen, ist, wenn das Programm für eine Art von E / A blockieren muss, z. B. für Benutzereingaben in einem GUI-Programm. In diesen Fällen spielt es keine Rolle, welche Sprache Sie verwenden, da Sie durch die Geschwindigkeit, mit der Daten eingehen können, und nicht durch die Geschwindigkeit, mit der Sie sie verarbeiten können, eingeschränkt sind. In diesem Fall spielt es keine Rolle, ob Sie C, Java, C # oder sogar Perl verwenden. Sie können einfach nicht schneller gehen, als die Daten eingehen können.

Die andere wichtige Sache ist, dass die virtuelle Maschine durch die Verwendung der Garbage Collection und nicht der Verwendung geeigneter Zeiger eine Reihe von Optimierungen vornehmen kann, die in anderen Sprachen nicht verfügbar sind. Beispielsweise kann die JVM Objekte auf dem Heap verschieben, um ihn zu defragmentieren. Dies beschleunigt zukünftige Zuordnungen erheblich, da der nächste Index einfach verwendet werden kann, anstatt ihn in einer Tabelle nachzuschlagen. Moderne JVMs müssen den Speicher auch nicht freigeben. Stattdessen verschieben sie nur die lebenden Objekte, wenn sie GC durchführen, und der verbrauchte Speicher der toten Objekte wird im Wesentlichen kostenlos wiederhergestellt.

Dies bringt auch einen interessanten Punkt über C und noch mehr in C ++. Es gibt so etwas wie eine Designphilosophie: "Wenn Sie es nicht brauchen, zahlen Sie nicht dafür." Das Problem ist, dass Sie, wenn Sie es wollen, am Ende durch die Nase dafür bezahlen. Beispielsweise ist die vtable-Implementierung in Java in der Regel viel besser als C ++ - Implementierungen, sodass virtuelle Funktionsaufrufe viel schneller sind. Auf der anderen Seite haben Sie keine andere Wahl, als virtuelle Funktionen in Java zu verwenden, und sie kosten immer noch etwas, aber in Programmen, die viele virtuelle Funktionen verwenden, summieren sich die reduzierten Kosten.


1
"Die vtable-Implementierung in Java ist in der Regel viel besser als die von C ++ - Implementierungen, sodass virtuelle Funktionsaufrufe viel schneller sind." Wie um alles in der Welt können Sie schneller als MOV EAX, [ECX]; CALL [EAX + Someindex]; ? Wenn Sie eine Funktion nicht aufrufen können, ohne sie nachzuschlagen, sieht dies ziemlich optimal aus.
Frans-Willem

@Frans - Ein JIT-Compiler (wie Java HotSpot) kann die vtable-Suche einbinden, wenn er feststellt, dass ein bestimmtes Objekt immer von einem bestimmten Typ ist. C ++ wird dies auch tun, wenn es zur Kompilierungszeit dieselben Informationen kennt, diese Optimierung jedoch mit Java-Bytecode einfacher ist als mit x86-Maschinenanweisungen.
Tom

6
@James - Das Argument "E / A macht Leistung weniger wichtig" macht die Aussage "C ist schneller als andere Sprachen" nicht ungültig. Das ist kein grelles Loch, das ist ein Strohmann-Argument.
Tom

Es wäre besser gewesen, Cs String-Handling (und auch die Standard-C-Bibliothek) als Beispiel zu verwenden, da dies ein Bereich ist, in dem C schlecht ist. Die meisten anderen Sprachen sind besser, selbst mit vereinfachtem Startcode.
Donal Fellows

@DonalFellows Die mem * -Funktionen können bei einigen Aufgaben schneller sein als die str * -Funktionen, aber die Behandlung von Zeichenfolgen ist effizient, wenn sorgfältig vorgegangen wird. Haben Sie einen bestimmten Benchmark im Sinn?
Jasen

4

Es geht weniger um die Sprache als um die Werkzeuge und Bibliotheken. Die verfügbaren Bibliotheken und Compiler für C sind viel älter als für neuere Sprachen. Sie könnten denken, dies würde sie langsamer machen, aber au contraire.

Diese Bibliotheken wurden zu einer Zeit geschrieben, als Rechenleistung und Speicher einen hohen Stellenwert hatten. Sie mussten sehr effizient geschrieben werden, um überhaupt arbeiten zu können. Entwickler von C-Compilern hatten auch lange Zeit, um an allen möglichen cleveren Optimierungen für verschiedene Prozessoren zu arbeiten. Die Reife und breite Akzeptanz von C verschafft anderen Sprachen des gleichen Alters einen deutlichen Vorteil. Es gibt C auch einen Geschwindigkeitsvorteil gegenüber neueren Tools, bei denen die Rohleistung nicht so stark betont wird wie bei C.


4

Der Mangel an Abstraktion macht C schneller. Wenn Sie eine Ausgabeanweisung schreiben, wissen Sie genau, was passiert. Wenn Sie eine Ausgabeanweisung in Java schreiben, wird sie in eine Klassendatei kompiliert, die dann auf einer virtuellen Maschine ausgeführt wird, die eine Abstraktionsschicht einführt. Das Fehlen objektorientierter Funktionen als Teil der Sprache erhöht auch die Geschwindigkeit, mit der weniger Code generiert wird. Wenn Sie C als objektorientierte Sprache verwenden, führen Sie die gesamte Codierung für Dinge wie Klassen, Inharitenz usw. durch. Dies bedeutet, dass Sie für jeden etwas verallgemeinern, das für die Menge an Code und die Leistungsschwäche, für die Sie nur schreiben müssen, ausreichend ist was Sie brauchen, um die Arbeit zu erledigen.


4

Erstaunlich zu sehen, dass der alte Mythos "C / C ++ muss schneller sein als Java, weil Java interpretiert wird" immer noch lebendig ist. Es gibt Artikel, die einige Jahre zurückreichen , sowie neuere , die mit Konzepten oder Messungen erklären, warum dies einfach nicht immer der Fall ist .

Aktuelle Implementierungen virtueller Maschinen (und übrigens nicht nur die JVM) können die während der Programmausführung gesammelten Informationen nutzen, um den Code während der Ausführung mithilfe verschiedener Techniken dynamisch zu optimieren:

  • häufige Methoden zum Maschinencode rendern,
  • kleine Methoden einbinden,
  • Einstellung der Verriegelung

und eine Vielzahl anderer Anpassungen, die darauf basieren, zu wissen, was der Code tatsächlich tut, und auf den tatsächlichen Merkmalen der Umgebung, in der er ausgeführt wird.


Ich bin damit einverstanden, dass Java in den letzten Jahren erhebliche Leistungsverbesserungen vorgenommen hat, die es C in Bezug auf die Rohleistung viel näher bringen, aber es wird eine Weile dauern, bis die Tatsache, dass es so lange so langsam war, gelebt wird . Aber wer hat überhaupt über Java gesprochen?
Robert Gamble

Java ist eine "andere Sprache", auf die das OP verweist, nicht wahr?
Robert C. Barth

@ Robert: "andere Sprachen", Plural, keine Erwähnung einer anderen Sprache als C. Wie liest man möglicherweise "Java" daraus?
Robert Gamble

@Roberd: Einige der Antworten, die veröffentlicht wurden, bevor ich auf die Frage stieß, betrafen Java (oder andere Sprachen, deren Implementierung häufig über Interpreter oder VM erfolgt).
joel.neely

3
@Joel - Wenn Sie Ihre Zielhardware kennen, können die meisten Optimierungen, die die JVM zur Laufzeit vornehmen kann, auch mithilfe der profilgesteuerten Optimierung mit C oder C ++ durchgeführt werden. Das macht einen großen Unterschied und bringt C und C ++ im Allgemeinen wieder an die Spitze, da sie während der Ausführung nicht "lernen" müssen.
Tom

4

Der am schnellsten laufende Code wäre sorgfältig handgefertigter Maschinencode. Assembler wird fast genauso gut sein. Beide sind sehr niedrig und es erfordert viel Code, um Dinge zu tun. C liegt etwas über dem Assembler. Sie haben immer noch die Möglichkeit, Dinge auf einer sehr niedrigen Ebene in der tatsächlichen Maschine zu steuern, aber es gibt genug Abstraktion, um das Schreiben schneller und einfacher zu machen als Assembler. Andere Sprachen wie C # und JAVA sind noch abstrakter. Während Assembler und Maschinencode als Low-Level-Sprachen bezeichnet werden, werden C # und JAVA (und viele andere) als High-Level-Sprachen bezeichnet. C wird manchmal als Mittelsprache bezeichnet.


Während ich Ihre Antwort las, zogen nur zwei Wörter im gesamten Absatz meine Augen auf sie, wie ein Magnet, der Metalle zieht. Das Wort ist JAVA, zweimal im Absatz. Ich habe es noch nie in
Großbuchstaben gesehen

3

Nehmen Sie kein Wort dafür, sondern sehen Sie sich die Zerlegung für C und die Sprache Ihrer Wahl in einem leistungskritischen Teil Ihres Codes an. Ich denke, Sie können zur Laufzeit in Visual Studio einfach in das Demontagefenster schauen, um das zerlegte .Net zu sehen. Sollte möglich sein, wenn es für Java mit windbg schwierig ist, aber wenn Sie es mit .Net tun, wären viele der Probleme gleich.

Ich schreibe nicht gerne in C, wenn ich nicht muss, aber ich denke, dass viele der Behauptungen in diesen Antworten, die die Geschwindigkeit anderer Sprachen als C ankündigen, durch einfaches Zerlegen derselben Routine in C und aufgehoben werden können in der Sprache Ihrer Wahl auf höherer Ebene, insbesondere wenn viele Daten beteiligt sind, wie dies bei leistungskritischen Anwendungen üblich ist. Fortran kann eine Ausnahme in seinem Fachgebiet sein, weiß nicht. Ist es höher als C?

Beim ersten Vergleich von JITed-Code mit nativem Code wurden alle Fragen geklärt, ob .Net-Code vergleichbar mit C-Code ausgeführt werden kann. Die zusätzliche Abstraktionsebene und alle Sicherheitsüberprüfungen sind mit erheblichen Kosten verbunden. Die gleichen Kosten würden wahrscheinlich für Java anfallen, aber nehmen Sie nicht mein Wort und probieren Sie es an etwas aus, bei dem die Leistung entscheidend ist. (Weiß jemand genug über JITed Java, um eine kompilierte Prozedur im Speicher zu finden? Es sollte auf jeden Fall möglich sein)


2

1) Wie andere gesagt haben, tut C weniger für Sie. Keine Initialisierungsvariablen, keine Überprüfung der Array-Grenzen, keine Speicherverwaltung usw. Diese Funktionen in anderen Sprachen kosten Speicher und CPU-Zyklen, die C nicht ausgibt.

2) Antworten, die besagen, dass C weniger abstrahiert und daher schneller ist, sind meiner Meinung nach nur halb richtig. Wenn Sie einen "ausreichend fortgeschrittenen Compiler" für Sprache X hätten, könnte sich Sprache X der Geschwindigkeit von C annähern oder dieser entsprechen. Der Unterschied zu C besteht darin, dass sie so offensichtlich abgebildet wird (wenn Sie einen Architekturkurs belegt haben) und direkt zur Assemblersprache, die selbst ein naiver Compiler anständig machen kann. Für etwas wie Python benötigen Sie einen sehr fortgeschrittenen Compiler, um die wahrscheinlichen Objekttypen vorherzusagen und Maschinencode im laufenden Betrieb zu generieren. Die Semantik von C ist so einfach, dass ein einfacher Compiler dies gut kann.


2

In den guten alten Tagen gab es nur zwei Arten von Sprachen: kompiliert und interpretiert.

Kompilierte Sprachen verwendeten einen "Compiler", um die Sprachsyntax zu lesen und in identischen Assembler-Code umzuwandeln, der nicht nur direkt auf der CPU ausgeführt werden konnte. Interpretierte Sprachen verwendeten einige verschiedene Schemata, aber im Wesentlichen wurde die Sprachsyntax in eine Zwischenform konvertiert und dann in einem "Interpreter" ausgeführt, einer Umgebung zum Ausführen des Codes.

In gewisser Weise gab es also eine andere "Schicht" - den Interpreter - zwischen dem Code und der Maschine. Und wie immer bei einem Computer bedeutet mehr, dass mehr Ressourcen verwendet werden. Dolmetscher waren langsamer, weil sie mehr Operationen durchführen mussten.

In jüngerer Zeit haben wir mehr hybride Sprachen wie Java gesehen, die sowohl einen Compiler als auch einen Interpreter verwenden, damit sie funktionieren. Es ist kompliziert, aber eine JVM ist schneller, ausgefeilter und viel optimierter als die alten Interpreter, sodass sich die Leistung (im Laufe der Zeit) viel besser ändert, wenn sie nur direkt kompiliertem Code entspricht. Natürlich haben die neueren Compiler auch ausgefallenere Optimierungstricks, sodass sie tendenziell viel besseren Code generieren als früher. Aber die meisten Optimierungen machen meistens (wenn auch nicht immer) einen Kompromiss, so dass sie nicht immer unter allen Umständen schneller sind. Wie alles andere ist auch nichts kostenlos, daher müssen sich die Optimierer von irgendwoher rühmen (obwohl sie häufig CPU zur Kompilierungszeit verwenden, um Laufzeit-CPU zu sparen).

Zurück zu C, es ist eine einfache Sprache, die zu einer ziemlich optimierten Assembly kompiliert und dann direkt auf dem Zielcomputer ausgeführt werden kann. Wenn Sie in C eine Ganzzahl inkrementieren, ist es mehr als wahrscheinlich, dass es sich nur um einen Assembler-Schritt in der CPU handelt. In Java kann dies jedoch viel mehr sein (und auch ein bisschen Garbage Collection enthalten: -) C bietet Ihnen eine Abstraktion, die viel näher an der Maschine liegt (Assembler ist am nächsten), aber Sie müssen am Ende viel mehr Arbeit leisten, um sie zum Laufen zu bringen, und sie ist nicht so geschützt, einfach zu bedienen oder fehlerfreundlich. Die meisten anderen Sprachen bieten Ihnen eine höhere Abstraktion und kümmern sich um mehr der zugrunde liegenden Details für Sie. Im Austausch für ihre erweiterten Funktionen benötigen sie jedoch mehr Ressourcen, um ausgeführt zu werden. Wenn Sie einige Lösungen verallgemeinern, müssen Sie mit einem breiteren Spektrum von Computern umgehen.

Paul.


"Wenn Sie in C eine Ganzzahl erhöhen, ist es mehr als wahrscheinlich, dass es sich nur um einen Assembler-Schritt in der CPU handelt." Nicht genau richtig. Wenn sich diese Ganzzahl nicht im CPU-Register befindet, benötigen Sie den Maschinencode, um sie aus dem Speicher abzurufen, zu erhöhen und in den Speicher zurückzuschreiben. Etwa das Gleiche würde man erwarten, wenn Java-Code ausgeführt wird. Und ich habe keine Ahnung, warum "++ i" von sich aus einen GC-Zyklus auslösen würde.
quant_dev

@quant_dev: "Sie ... müssen ... es aus dem Speicher holen, inkrementieren, zurückschreiben ...". Vielleicht, vielleicht nicht. Der x86 verfügt beispielsweise über Anweisungen, die Daten im Speicher verarbeiten. ++ikönnte zu "add [ebp - 8], 1" kompiliert werden. Um nicht zu sagen, dass das Abrufen, Inkrementieren und Speichern nicht immer noch stattfindet, aber dies wird von der CPU erledigt und ist nur eine Anweisung, wie Paul sagte.
P Daddy

... was für den POV der Leistung immer noch irrelevant ist, da es sich möglicherweise nur um eine Anweisung handelt, aber immer noch darauf gewartet wird, dass die Daten bei der CPU ankommen. Cache fehlt und das alles.
quant_dev

Nein, ich würde nicht sagen, dass es irrelevant ist. Ein CPU-Befehl belegt normalerweise weniger Codebytes als mehrere CPU-Befehle, was zu einer besseren Cache-Leistung im Codesegment führt. Ein CPU-Befehl nimmt auch weniger Platz in der CPU-Pipeline ein, und die mehreren Schritte (Abrufen, Inkrementieren, Speichern) können - möglicherweise parallel - von den separaten Pipeline-Stufen ausgeführt werden. Tatsächlich können einige Teile eines Vorgangs sogar übersprungen werden, wenn sie mit anderen Vorgängen in der Pipeline verschmolzen werden können. Beispielsweise kann das Speichern eines Werts mit einem anschließenden Laden desselben Werts verschmolzen werden.
P Daddy

2

Abgesehen von fortschrittlichen Optimierungstechniken wie Hot-Spot-Optimierung , vorkompilierten Metaalgorithmen und verschiedenen Formen der Parallelität korreliert die grundlegende Geschwindigkeit einer Sprache stark mit der impliziten Komplexität hinter den Kulissen, die zur Unterstützung der üblichen Vorgänge erforderlich ist innerhalb der inneren Schleifen angegeben werden .

Am offensichtlichsten ist möglicherweise die Gültigkeitsprüfung indirekter Speicherreferenzen - beispielsweise das Überprüfen von Zeigern auf nullund das Überprüfen von Indizes anhand von Arraygrenzen. Die meisten Hochsprachen führen diese Überprüfungen implizit durch, C jedoch nicht. Dies ist jedoch nicht unbedingt eine grundlegende Einschränkung dieser anderen Sprachen - ein ausreichend geschickter Compiler kann diese Überprüfungen möglicherweise durch irgendeine Form von schleifeninvarianter Codebewegung aus den inneren Schleifen eines Algorithmus entfernen .

Der grundlegendere Vorteil von C (und in ähnlichem Maße das eng verwandte C ++) ist die starke Abhängigkeit von der stapelbasierten Speicherzuweisung , die für Zuweisung, Freigabe und Zugriff von Natur aus schnell ist . In C (und C ++) kann der primäre Aufrufstapel zur Zuweisung von Grundelementen, Arrays und Aggregaten ( struct/ class) verwendet werden.

Während C die Möglichkeit bietet, Speicher beliebiger Größe und Lebensdauer dynamisch zuzuweisen (unter Verwendung des sogenannten "Heaps"), wird dies standardmäßig vermieden (stattdessen wird der Stapel verwendet).

Interessanterweise ist es manchmal möglich, die C-Speicherzuweisungsstrategie in den Laufzeitumgebungen anderer Programmiersprachen zu replizieren. Dies wurde von asm.js demonstriert , mit dem in C oder C ++ geschriebener Code in eine Teilmenge von JavaScript übersetzt und sicher in einer Webbrowser-Umgebung ausgeführt werden kann - mit nahezu nativer Geschwindigkeit.


Abgesehen davon ist ein weiterer Bereich, in dem C und C ++ die meisten anderen Sprachen hinsichtlich der Geschwindigkeit übertreffen, die Möglichkeit, sich nahtlos in native Maschinenbefehlssätze zu integrieren. Ein bemerkenswertes Beispiel hierfür ist die (compiler- und plattformabhängige) Verfügbarkeit von SIMD-Intrinsics, die die Konstruktion benutzerdefinierter Algorithmen unterstützen, die die mittlerweile nahezu allgegenwärtige Parallelverarbeitungshardware nutzen - und gleichzeitig die von der Sprache bereitgestellten Datenzuordnungsabstraktionen verwenden (niedriger) Die Registerzuordnung auf der Ebene wird vom Compiler verwaltet.


1
Einige dieser Speicherzuweisungsvorteile von C können wahrscheinlich auch von cleveren Compilern in anderen Sprachen repliziert werden (siehe hier ). Ich habe jedoch den Eindruck, dass dies strukturell sehr schwierig ist - insbesondere für nicht-primitive Datentypen. In diesem Beitrag wird die Idee eines nicht maskierenden Objekts erwähnt, das als Optimierung in Java stapelweise zugewiesen werden kann.
Nobar

2

Ich habe eine Antwort auf den Link gefunden, warum einige Sprachen schneller und einige langsamer sind. Ich hoffe, dies wird mehr darüber klären, warum C oder C ++ schneller als andere ist. Es gibt auch einige andere Sprachen, die schneller als C sind, aber wir können nicht benutze sie alle. Einige Erklärungen -

Einer der Hauptgründe, warum Fortran wichtig bleibt, ist seine Schnelligkeit: In Fortran geschriebene Routinen zur Zahlenverarbeitung sind in der Regel schneller als in den meisten anderen Sprachen geschriebene Routinen. Die Sprachen, die in diesem Bereich mit Fortran konkurrieren - C und C ++ - werden verwendet, weil sie mit dieser Leistung konkurrieren.

Dies wirft die Frage auf: Warum? Was macht C ++ und Fortran so schnell und warum übertreffen sie andere beliebte Sprachen wie Java oder Python?

Interpretieren versus Kompilieren Es gibt viele Möglichkeiten, Programmiersprachen zu kategorisieren und zu definieren, je nachdem, welchen Programmierstil sie fördern und welche Funktionen sie bieten. Bei der Betrachtung der Leistung besteht der größte Unterschied zwischen interpretierten und kompilierten Sprachen.

Die Kluft ist nicht schwer; Vielmehr gibt es ein Spektrum. An einem Ende haben wir traditionelle kompilierte Sprachen, eine Gruppe, die Fortran, C und C ++ umfasst. In diesen Sprachen gibt es eine diskrete Kompilierungsphase, die den Quellcode eines Programms in eine ausführbare Form übersetzt, die der Prozessor verwenden kann.

Dieser Kompilierungsprozess besteht aus mehreren Schritten. Der Quellcode wird analysiert und analysiert. An dieser Stelle können grundlegende Codierungsfehler wie Tippfehler und Rechtschreibfehler erkannt werden. Der analysierte Code wird verwendet, um eine speicherinterne Darstellung zu generieren, mit der auch Fehler erkannt werden können - diesmal semantische Fehler wie das Aufrufen nicht vorhandener Funktionen oder der Versuch, arithmetische Operationen für Textzeichenfolgen auszuführen.

Diese speicherinterne Darstellung wird dann verwendet, um einen Codegenerator anzutreiben, der Teil, der ausführbaren Code erzeugt. Die Codeoptimierung zur Verbesserung der Leistung des generierten Codes wird zu verschiedenen Zeitpunkten innerhalb dieses Prozesses durchgeführt: Optimierungen auf hoher Ebene können für die Codedarstellung durchgeführt werden, und Optimierungen auf niedrigerer Ebene werden für die Ausgabe des Codegenerators verwendet.

Die eigentliche Ausführung des Codes erfolgt später. Der gesamte Kompilierungsprozess wird einfach verwendet, um etwas zu erstellen, das ausgeführt werden kann.

Am anderen Ende haben wir Dolmetscher. Die Interpreter enthalten eine Parsing-Phase, die der des Compilers ähnelt. Diese wird jedoch verwendet, um die direkte Ausführung zu steuern, wobei das Programm sofort ausgeführt wird.

Der einfachste Interpreter enthält ausführbaren Code, der den verschiedenen von der Sprache unterstützten Funktionen entspricht. Er verfügt also über Funktionen zum Hinzufügen von Zahlen, zum Verknüpfen von Zeichenfolgen und zu allen anderen Funktionen einer bestimmten Sprache. Beim Parsen des Codes wird die entsprechende Funktion nachgeschlagen und ausgeführt. Im Programm erstellte Variablen werden in einer Art Nachschlagetabelle gespeichert, die ihre Namen ihren Daten zuordnet.

Das extremste Beispiel für den Interpreter-Stil ist eine Batch-Datei oder ein Shell-Skript. In diesen Sprachen ist der ausführbare Code oft nicht einmal in den Interpreter selbst integriert, sondern in separate, eigenständige Programme.

Warum wirkt sich dies auf die Leistung aus? Im Allgemeinen verringert jede Indirektionsebene die Leistung. Der schnellste Weg, zwei Zahlen hinzuzufügen, besteht beispielsweise darin, beide Zahlen in Registern im Prozessor zu haben und den Befehl add des Prozessors zu verwenden. Das können kompilierte Programme. Sie können Variablen in Register einfügen und Prozessoranweisungen nutzen. In interpretierten Programmen erfordert dieselbe Addition möglicherweise zwei Suchvorgänge in einer Variablentabelle, um die hinzuzufügenden Werte abzurufen, und ruft dann eine Funktion auf, um die Addition durchzuführen. Diese Funktion verwendet möglicherweise denselben Prozessorbefehl wie das kompilierte Programm, um die eigentliche Addition durchzuführen, aber die zusätzliche Arbeit, bevor der Befehl tatsächlich verwendet werden kann, verlangsamt die Arbeit.

Wenn Sie mehr wissen möchten, überprüfen Sie bitte die Quelle


1

Einige C ++ - Algorithmen sind schneller als C, und einige Implementierungen von Algorithmen oder Entwurfsmustern in anderen Sprachen können schneller als C sein.

Wenn Leute sagen, dass C schnell ist und dann über eine andere Sprache sprechen, verwenden sie im Allgemeinen die Leistung von C als Benchmark.


2
"Einige C ++ - Algorithmen sind schneller als C" ist nicht sinnvoll. Jeder "C ++ - Algorithmus" kann in C geschrieben werden und umgekehrt. Algorithmen sind sprachunabhängig. C ++ fügt C im Wesentlichen Funktionen hinzu - und keine dieser neuen Funktionen führt zu schnelleren Algorithmen (obwohl sie möglicherweise einfacher zu schreiben sind).
Joseph Garvin

1
Die klassische Zurechtweisung ist std :: sort algorithm .. std :: sort ist schneller als jeder Sortieralgorithmus in C - die einzige Möglichkeit, die gleiche Leistung in C zu erzielen, besteht darin, sie überall fest zu codieren oder Makros zu verwenden - und selbst dann Der Compiler muss weniger Informationen optimieren.
Arafangion

1

Mit modernen optimierenden Compilern ist es höchst unwahrscheinlich, dass ein reines C-Programm, wenn überhaupt, viel schneller als kompilierter .net-Code ist. Mit der Produktivitätssteigerung, die Frameworks wie .net dem Entwickler bieten, können Sie Dinge an einem Tag erledigen, der in regulären C Wochen oder Monate gedauert hat. In Verbindung mit den günstigen Hardwarekosten im Vergleich zum Gehalt eines Entwicklers ist das Schreiben einfach viel billiger das Zeug in einer Hochsprache und werfen Hardware auf jede Langsamkeit.

Der Grund, warum Jeff und Joel davon sprechen, dass C die "echte Programmiersprache" ist, liegt darin, dass C kein Händchen hält. Sie müssen Ihr eigenes Gedächtnis zuweisen, dieses Gedächtnis freigeben, Ihre eigenen Grenzüberprüfungen durchführen usw. Es gibt so etwas nicht als neues Objekt (); Es gibt keine Garbage Collection, Klassen, OOP, Entity Frameworks, LINQ, Eigenschaften, Attribute, Felder oder ähnliches. Sie müssen Dinge wie Zeigerarithmetik und das Dereferenzieren eines Zeigers kennen. Und im Übrigen wissen und verstehen, was ein Zeiger ist. Sie müssen wissen, was ein Stapelrahmen ist und was der Befehlszeiger ist. Sie müssen das Speichermodell der CPU-Architektur kennen, an der Sie arbeiten. Es gibt viel implizites Verständnis der Architektur eines Mikrocomputers (normalerweise derMikrocomputer, an dem Sie arbeiten) beim Programmieren in C, der einfach nicht vorhanden oder notwendig ist, wenn Sie in etwas wie C # oder Java programmieren. Alle diese Informationen wurden in den Compiler- (oder VM-) Programmierer geladen.


"Mehr Hardware beim Problem" funktioniert nur in Umgebungen, in denen dies tatsächlich möglich ist. Der eingebettete Markt ist ein perfektes Gegenbeispiel (und das ist ein massiver Markt).
Bob Somers

Jeff und Joel bloggen ausschließlich über Geschäftssysteme, nicht über eingebettete Systeme. Es ist daher anzunehmen, dass dies der Kontext ist, in dem diese Frage gestellt wurde.
Robert C. Barth

1) .net-Code läuft so schnell wie C-Code? Haben Sie jemals ein C-Programm geschrieben? 2) Die Mentalität "Mehr Hardware auf das Problem werfen" ist, warum mein 1,3-GHz-Dual-Core-2-GB-Computer kaum mit Windows XP mithalten kann, während mein 800-MHz-512-MB-Computer mit der neuesten Version von Ubuntu fliegt.
Robert Gamble

Ja, ich habe C geschrieben. Es ist nicht so herrlich, wie die Leute es sich vorstellen. Und Projekte kosten zu viel. Es ist ein einfacher Fall von Wirtschaft. Ich habe Win2k jahrelang auf einem Pentium Pro 180MHz mit 768MB RAM als Mail- und Webserver ausgeführt. Es lief gut. Anekdoten bedeuten nichts.
Robert C. Barth

C ist nicht "herrlich", aber es ist schnell. Ich habe genug C- und C # -Code geschrieben, um zu wissen, dass C fast immer viel schneller als C # ist, während dieselbe Aufgabe ausgeführt wird. Bei einigen Aufgaben dauert die Entwicklung in höheren Sprachen länger als bei höheren Sprachen, aber es geht nur darum, das richtige Werkzeug für den Job zu verwenden, und manchmal ist es C.
Robert Gamble

1

Es ist der Unterschied zwischen automatischen und manuellen, übergeordneten Sprachen sind Abstraktionen, die somit automatisiert werden. C / C ++ werden manuell gesteuert und gehandhabt, selbst Fehlerprüfcode ist manchmal eine manuelle Arbeit.

C und C ++ sind ebenfalls kompilierte Sprachen, was bedeutet, dass nichts davon überall im Geschäft läuft. Diese Sprachen müssen für die Hardware, mit der Sie arbeiten, genau abgestimmt werden, um eine zusätzliche Ebene von Gotcha hinzuzufügen. Dies ist jedoch etwas beunruhigend, da C / C ++ - Compiler auf allen Plattformen immer häufiger eingesetzt werden. Sie können plattformübergreifende Kompilierungen durchführen. Es ist immer noch nicht überall eine Situation, in der Sie Compiler A grundsätzlich anweisen, gegen Compiler B denselben Code mit unterschiedlicher Architektur zu kompilieren.

Unter dem Strich sollen C-Sprachen nicht leicht zu verstehen oder zu begründen sein, weshalb sie auch als Systemsprachen bezeichnet werden. Sie kamen vor all diesem hochrangigen Abstraktionsquatsch heraus. Aus diesem Grund werden sie auch nicht für die Front-End-Webprogrammierung verwendet. Sie sind einfach nicht für die Aufgabe geeignet, sie wollen komplexe Probleme lösen, die mit herkömmlichen Sprachwerkzeugen nicht gelöst werden können.

Aus diesem Grund gibt es verrückte Dinge wie (Mikroarchitekturen, Treiber, Quantenphysik, AAA-Spiele, Betriebssysteme), für die C und C ++ einfach gut geeignet sind. Geschwindigkeit und Zahlenkalkulation sind die Hauptbereiche.



1

Es gibt viele Gründe, darunter:

  • Es wird in Assemblersprache kompiliert.
  • Es ist statisch typisiert.
  • Keine Müllabfuhr.
  • Keine Fehlerbehandlung.
  • Viele Programmiersprachen fügen neue Funktionen hinzu. Ein Teil der Philosophie von C besteht darin, die Dinge einfach zu halten, anstatt weitere Funktionen hinzuzufügen.

Warum sollte es schneller sein, weil es nicht objektorientiert ist?
sb27

A) Objektorientierte Programmierung erfordert Speicherbereinigung. B) Große Funktionen wie objektorientierte Programmierung erhöhen die Komplexität des Compilers.
Sapphire_Brick

A) Nein. Siehe C ++ oder Rust. B) Ja, aber es gibt dem Compiler auch Möglichkeiten für neue Optimierungen.
sb27

A) Rust hat eine Garbage Collection zur Kompilierungszeit und c ++ eine Garbage Collection für Klassen. Deshalb hat es Destruktoren. B) Optimierte Komplexität ist immer noch Komplexität
Sapphire_Brick

A) Es handelt sich nicht um eine Speicherbereinigung. Die Speicherverwaltung muss auch dann erfolgen, wenn Sie Ihr Programm in Assembly B) Nein erstellen. Mehr Abstraktion ermöglicht es dem Optimierer, bessere Annahmen zu treffen.
sb27
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.