36 Stimmen

Was kostet ein Funktionsanruf?

Verglichen mit

  • Einfachen Speicherzugriff
  • Plattenzugriff
  • Speicherzugriff auf einem anderen Computer(im selben Netzwerk)
  • Plattenzugriff auf einem anderen Computer(im selben Netzwerk)

in C++ unter Windows.

30voto

mfx Punkte 6908

Relative timings (sollte nicht um mehr als einen Faktor von 100 abweichen ;-)

  • Speicherzugriff im Cache = 1
  • Funktionsaufruf/Rückgabe im Cache = 2
  • Speicherzugriff außerhalb des Caches = 10 .. 300
  • Plattenzugriff = 1000 .. 1e8 (amortisiert abhängig von der Anzahl der übertragenen Bytes)
    • abhängig hauptsächlich von den Suchzeiten
    • die Übertragung selbst kann ziemlich schnell sein
    • beinhaltet mindestens einige tausend Operationen, da die Benutzer-/System-Schwelle mindestens zweimal überschritten werden muss; eine I/O-Anforderung muss geplant werden, das Ergebnis muss zurückgeschrieben werden; möglicherweise werden Puffer allokiert...
  • Netzwerkanrufe = 1000 .. 1e9 (amortisiert abhängig von der Anzahl der übertragenen Bytes)
    • das gleiche Argument wie bei Festplattenzugriff
    • die Rohübertragungsgeschwindigkeit kann ziemlich hoch sein, aber auf dem anderen Computer muss ein bestimmter Prozess die eigentliche Arbeit machen

0 Stimmen

Alle waren einverstanden, außer soweit ich weiß, ist der Speicherzugriff außerhalb des Cache ungefähr 200-300-mal langsamer als der Cache-Zugriff.

0 Stimmen

Geändert. Der Bereich von 10... soll auch die L1-Caches einschließen. Außerdem möchte ich nicht den Eindruck erwecken, dass ein Festplattenzugriff so schnell wie ein Speicherzugriff sein kann; die Situation ist nicht so schlimm ;-)

0 Stimmen

In deinem Cache-Figur - vergisst du nicht die Argumentbehandlung?

19voto

jW. Punkte 8980

Ein Funktionsaufruf ist einfach eine Verschiebung des Rahmenzeigers im Speicher auf den Stapel und die Hinzufügung eines neuen Rahmens oben darauf. Die Funktionparameter werden in lokale Register verschoben und der Stapelzeiger wird zum neuen oberen Rand des Stapels verschoben, um die Funktion auszuführen.

Im Vergleich zur Zeit

Funktionsaufruf ~ einfacher Speicherzugriff
Funktionsaufruf < Festplattenzugriff
Funktionsaufruf < Speicherzugriff auf einem anderen Computer
Funktionsaufruf < Festplattenzugriff auf einem anderen Computer

0 Stimmen

Hast du wirklich "Verschiebung des Stack-Zeigers" gemeint? "Verschiebung des Befehlszeigers" würde mir passender erscheinen. Ich würde es so beschreiben: IP wird auf den Stapel geschoben, IP wird auf die Funktionsadresse gesetzt, SP wird erhöht, um Speicherplatz für lokale Variablen zu reservieren (kann die Erstellung des Stapelrahmens umfassen)

0 Stimmen

Vielen Dank für die Klarstellung! Ich werde meine Antwort aktualisieren für alle, die in der Zukunft browsen.

8voto

Ferruccio Punkte 96076

Verglichen mit einem einfachen Speicherzugriff - etwas mehr, wirklich vernachlässigbar.

Verglichen mit allem anderen aufgelisteten - Größenordnungen weniger.

Dies sollte für praktisch jede Sprache auf jedem Betriebssystem gelten.

4voto

Torlack Punkte 4287

Im Allgemeinen wird ein Funktionsaufruf etwas langsamer sein als der Speicherzugriff, da tatsächlich mehrere Speicherzugriffe durchgeführt werden müssen, um den Aufruf auszuführen. Zum Beispiel sind für die meisten Funktionsaufrufe unter Verwendung von __stdcall auf x86 mehrere Pushes und Pops des Stacks erforderlich. Aber wenn Ihr Speicherzugriff zu einer Seite erfolgt, die sich nicht einmal im L2-Cache befindet, kann der Funktionsaufruf deutlich schneller sein, wenn das Ziel und der Stack alle im CPU-Speicher-Cache sind.

Für alles andere ist ein Funktionsaufruf um viele (viele) Größenordnungen schneller.

3voto

Steve Jessop Punkte 264569

Unter der Annahme, dass Sie den Overhead des Anrufs selbst meinen, anstatt was der Angerufene tun könnte, ist es definitiv viel, viel schneller als alles außer dem "einfachen" Speicherzugriff.

Es ist wahrscheinlich langsamer als der Speicherzugriff, aber beachten Sie, dass der Compiler Inline-Aufrufe tätigen kann, sodass der Overhead für Funktionen manchmal null ist. Selbst wenn nicht, ist es zumindest auf einigen Architekturen möglich, dass einige Aufrufe zu bereits im Befehlscache enthaltenem Code schneller sind als der Zugriff auf den Hauptspeicher (ungepuffert). Es hängt davon ab, wie viele Register vor dem Anruf auf den Stapel verschoben werden müssen und solche Dinge. Konsultieren Sie Ihre Compiler- und Aufrufkonventionsdokumentation, obwohl Sie es wahrscheinlich nicht schneller herausfinden können als durch das Disassemblieren des ausgegebenen Codes.

Bedenken Sie auch, dass "einfacher" Speicherzugriff manchmal nicht so einfach ist - wenn das Betriebssystem die Seite von der Festplatte laden muss, haben Sie eine lange Wartezeit vor sich. Das Gleiche gilt, wenn Sie in Code springen, der derzeit auf der Festplatte ausgelagert ist.

Wenn die zugrunde liegende Frage ist: "Wann sollte ich meinen Code optimieren, um die Gesamtzahl der Funktionenaufrufe zu minimieren?", dann ist die Antwort "sehr nahe an so gut wie nie".

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X