Effizienz der C-Variablendeklaration [duplizieren]

7

Wie lange dauert es, eine Variable in C zu deklarieren, zum Beispiel int x oder unsigned long long var ? Ich frage mich, ob es meinen Code in so etwas beschleunigen würde.

%Vor%

Wäre es schneller, oder ist es einfacher nicht?

%Vor%

Danke für die Hilfe.

    
Michael Dickens 24.12.2009, 02:20
quelle

12 Antworten

8

Immer wenn Sie eine Frage zur Leistung haben, ist es am besten, wenn Sie eine Schleife um ihn legen (Millionen von Iterationen) und die Zeit messen. Aber in diesem Fall werden Sie wahrscheinlich feststellen, dass keinen Unterschied macht.

Es ist wichtiger, die Absichten Ihres Codes richtig auszudrücken. Wenn Sie die Variable außerhalb Ihrer Schleife benötigen, delarieren Sie sie außerhalb. Wenn Sie nur die Variable innerhalb der Schleife benötigen, deklarieren Sie sie innerhalb.

Sie sollten Variablen immer im engsten möglichen Umfang deklarieren und initialisieren.

Sie sollten sich sowieso keine Gedanken über diese Arten von Mikrooptimierungen machen (außer in den seltensten, seltensten Fällen). Wenn Sie wirklich sich Gedanken über mögliche Verbesserungen in der Größenordnung von Nanosekunden machen müssen, messen Sie den Unterschied. Es ist sehr unwahrscheinlich, dass Ihre Variablendeklarationen der größte Engpass in Ihrer Anwendung sein werden.

    
Robert Cartaino 24.12.2009, 02:32
quelle
14

Ein Ratschlag: Hören Sie auf, sich darüber Gedanken zu machen, welche Sprachkonstrukte mikroskopisch schneller oder langsamer sind als die anderen, und konzentrieren Sie sich stattdessen darauf, welche Sie sich am besten ausdrücken können.

Um herauszufinden, wo sich Ihr Code befindet, verwenden Sie einen Profiler.

Und wie andere darauf hingewiesen haben, sind Deklarationen reine Kompilierungszeiten, sie beeinflussen die Ausführungszeit nicht.

    
Ned Batchelder 24.12.2009 02:32
quelle
9

Es macht keinen Unterschied. In einer herkömmlichen Implementierung erzeugt die Deklaration selbst (mit Ausnahme der Initialisierung) keine Maschinenanweisungen. Der Prologcode der Funktion weist normalerweise im Stapel allen lokalen Variablen Speicherplatz zu, unabhängig davon, wo sie deklariert sind.

Wenn Sie jedoch deklarieren, dass Ihre lokalen Variablen die Leistung Ihres Codes indirekt beeinflussen können, zumindest theoretisch. Wenn Sie die Variablen so lokal wie möglich deklarieren (Ihre erste Variante), resultiert dies in der Regel in einer kleineren Größe des von der Funktion für ihre lokalen Variablen reservierten Stack-Rahmens (da dieselbe Position im Stack von verschiedenen lokalen Variablen gemeinsam genutzt werden kann) zu anderen Zeiten). Ein kleinerer Stapelrahmen reduziert den allgemeinen Stapelspeicherverbrauch, d. H. Wenn verschachtelte Funktionsaufrufe ausgeführt werden, wächst die Stapelgröße nicht so schnell (besonders bemerkbar bei rekursiven Funktionen). Es verbessert im Allgemeinen die Leistung, da neue Stapelseitenzuweisungen weniger häufig auftreten und die Stapelspeicherposition besser wird.

Die letztgenannten Überlegungen sind natürlich plattformabhängig. Es kann sich sehr wenig oder gar nicht auf Ihre Plattform und / oder Ihre Anwendungen auswirken.

    
AnT 24.12.2009 02:36
quelle
5

Es dauert keine Zeit. Der Speicher für globale Variablen wird beim Start zugewiesen, und das "Deklarieren" von Variablen auf dem Stapel beinhaltet einfach, wie weit der Stapelzeiger sich bewegt, wenn die Funktion aufgerufen wird.

    
rlbond 24.12.2009 02:26
quelle
4

-Deklarationen sind reine Kompilierzeit, sie kosten nichts zur Laufzeit¹. Aber das erste Stück Code ist aus zwei Gründen immer noch besser als das zweite.

  • Sie sollten Variablen immer initialisieren, wenn Sie sie deklarieren, so dass sie niemals nicht initialisierte Werte haben können. Dies geht Hand in Hand mit
  • verwenden immer den engsten möglichen Gültigkeitsbereich für Variablendeklarationen

So ist Ihr erstes Beispiel, obwohl nicht schneller als das zweite, immer noch besser.

Und all die Leute, die ihm gesagt haben, dass er seinen Code nicht vorzeitig oder nur auf Mikroebene optimieren soll, sind falsch. Es ist nie schlecht zu wissen, wie teuer verschiedene Code-Teile sind. Die besten Programmierer haben ein solides, fast unbewusstes Verständnis für die Kosten verschiedener Strategien und berücksichtigen dies automatisch beim Design. Die Art, wie Sie zu diesem Programmierer werden, besteht darin, genau diese Art von Frage zu stellen, wenn Sie ein Anfänger sind.

¹ Tatsächlich gibt es kleine Kosten, wenn jede Funktion Speicherplatz für lokale Variablen zuweist, aber diese Kosten sind gleich, unabhängig davon, wie viele lokale Variablen es gibt *.

* ok, das ist nicht wirklich wahr, aber die Kosten hängen nur vom Gesamtvolumen ab, nicht von der Anzahl der Variablen.

    
John Knoeller 24.12.2009 03:17
quelle
3

Die Erklärung braucht keine Zeit.

Der Compiler interpretiert diese Zeile als Benachrichtigung, dass Platz auf dem Stack vorhanden sein muss.

    
Drew Dormann 24.12.2009 02:26
quelle
1

Ich wette, die kompilierte Binärdatei wird in beiden Fällen identisch sein.

    
Nicolás 24.12.2009 03:26
quelle
1

Wie andere schon gesagt haben, sollte es keine Zeit brauchen. Daher müssen Sie diese Entscheidung auf der Grundlage anderer Faktoren treffen: Was würde Ihren Code lesbarer und weniger fehleranfällig machen? Es wird allgemein als eine gute Vorgehensweise angesehen, eine Variable so nahe wie möglich an ihrer Verwendung zu deklarieren (so dass Sie die Deklaration und Verwendung auf einmal sehen können). Wenn es nur im inneren Bereich verwendet wird, dann deklariere es einfach in diesem Bereich - vergiss die Leistung auf diesem.

    
EMP 24.12.2009 02:30
quelle
1

Das Deklarieren von Variablen braucht Zeit, da es Maschinensprachanweisungen ergibt, die den Platz für die Variablen auf dem Stapel zuweisen. Dies ist einfach ein Inkrement des Stack-Zeigers, der eine winzige, aber von Null verschiedene Zeit benötigt.

Ich glaube, Ihre Frage ist, ob mehr Zeit benötigt wird (d. h. mehr Stapelinkrement-Operationen), wenn die Variable innerhalb der Schleife deklariert wird. Die Antwort ist nein, da der Stack nur einmal für den Schleifenblock inkrementiert wird, nicht jedes Mal, wenn die Schleife ausgeführt wird. Es wird also auch keinen Unterschied in der Zeit geben, selbst wenn die Schleife zig Millionen von Zillionen von Malen ausgeführt wird.

    
Larry Watanabe 24.12.2009 02:32
quelle
1

Haftungsausschluss: Was genau passiert, hängt von Ihrem Compiler, Ihrer Architektur usw. ab. Aber konzeptionell geht es hier weiter:

Wenn Sie eine Variable innerhalb einer Methode deklarieren, wird sie auf dem Stack zugeordnet. Wenn Sie etwas auf dem Stapel zuweisen, wird der Stapelzeiger nur um die Größe der Variablen erhöht. Wenn also SP die Speicheradresse des obersten Stacks darstellt, wird char x in SP += 1 und int x in SP += 4 (auf einer 32-Bit-Maschine) deklariert.

Wenn die Funktion beendet wird, wird der Stapelzeiger an die Stelle zurückgesetzt, an der er vor dem Aufruf der Methode war. Also ist die Freigabe auch schnell.

Also, in jedem Fall ist es nur ein Add, das unabhängig von der Datenmenge die gleiche Zeit benötigt.

Ein intelligenter Compiler kombiniert mehrere Variablendeklarationen zu einem einzigen Add.

Wenn Sie eine Variable innerhalb einer Schleife deklarieren, könnte theoretisch der Stapelzeiger bei jeder Iteration durch die Schleife geändert werden, aber ein intelligenter Compiler wird das wahrscheinlich auch nicht tun.

(Eine bemerkenswerte Ausnahme ist C ++, die zusätzliche Arbeit leistet, da sie Konstruktoren und Destruktoren aufrufen muss, wenn das Objekt mit dem zugewiesenen Stapel erstellt oder zerstört wird.)

    
benzado 24.12.2009 02:33
quelle
1

Ich würde mich hier und dort nicht um eine Nanosekunde kümmern. Wenn Sie nicht auf den Wert zugreifen müssen, nachdem die for-Schleife beendet hat, lassen Sie die Variable innerhalb der Schleife: sie ist näher an dem Code, der sie verwendet (Ihr Code wird lesbarer) und ihr Geltungsbereich wird durch die Schleife selbst begrenzt werden (Ihr Code wird eleganter und weniger fehleranfällig sein).

    
Federico A. Ramponi 24.12.2009 02:30
quelle
0

Die Variablendeklaration wird vom Compiler in eine Stapelspeicherreservierung umgewandelt. Wie funktioniert diese Arbeit nun vollständig plattformabhängig? Auf x86 und ziemlich jeder populären Architektur ist dies nur eine Subtraktion von der Adresse des Stapelrahmens und / oder Indexierungsadressierungsmodus, um von der Oberseite des Stapels zuzugreifen. All dies kommt mit den Kosten einer einfachen Subtraktion \ Addition, die wirklich irrelevant ist.

Technisch ist das zweite Beispiel weniger effizient, da die Deklaration bei jedem Eintrag in den Schleifenbereich auftritt, d. h. bei jeder Schleifeniteration. Es besteht jedoch eine 99,99% ige Chance, dass der Stack-Speicherplatz nur einmal reserviert wird. Selbst die Zuweisungsoperation wird wegoptimiert, obwohl sie technisch bei jeder Schleifeniteration durchgeführt werden sollte. Jetzt in C ++ kann das viel schlimmer werden, wenn die Variable einen Konstruktor hat, der dann bei jeder Schleifeniteration ausgeführt wird.

Und als Fazit sollten Sie sich keine Sorgen um solche Probleme ohne richtiges Profiling machen. Und selbst dann gibt es viel mehr wertvolle Fragen, die Sie sich hier stellen sollten, wie "Was ist der beste Weg dies zu tun, was ist leichter zu verstehen und zu erhalten, etc.".

    
Inso Reiges 24.12.2009 12:16
quelle