Wann sollte ich die Inline-function verwenden und wann nicht?

Ich weiß, dass Inline ein Hinweis oder eine Anforderung an den Compiler ist und dass es verwendet wird, um functionsaufruf-Overheads zu vermeiden.

Auf welcher Grundlage kann man also feststellen, ob eine function für Inlining geeignet ist oder nicht? In welchem ​​Fall sollte man das Inlining vermeiden?

Solutions Collecting From Web of "Wann sollte ich die Inline-function verwenden und wann nicht?"

Die Kosten eines functionsaufrufs zu vermeiden, ist nur die halbe Wahrheit.

machen:

  • Verwenden Sie inline anstelle von #define
  • sehr kleine functionen sind gute Kandidaten für inline : schnellerer Code und kleinere ausführbare Dateien (mehr Chancen, im Code-Cache zu bleiben)
  • Die function ist klein und wird sehr oft aufgerufen

nicht:

  • große functionen: führt zu größeren ausführbaren Dateien, die die performance erheblich beeinträchtigen, unabhängig von der schnelleren Ausführung, die sich aus dem Aufruf-Overhead ergibt
  • Inline-functionen, die E / A-gebunden sind
  • Die function wird selten verwendet
  • Konstruktoren und Destruktoren: Auch wenn sie leer sind, generiert der Compiler Code für sie
  • Brechen der Binärkompatibilität beim Entwickeln von Bibliotheken:
    • Inline eine bestehende function
    • eine Inline-function ändern oder eine Inline-function nicht inline machen: vorherige Version der Bibliothek ruft die alte Implementierung auf

Wenn Sie eine Bibliothek entwickeln, sollten Sie:

  • Fügen Sie einen nichtlinearen virtuellen Destruktor hinzu, auch wenn der Rumpf leer ist
  • mache alle Konstruktoren nicht-inline
  • Schreiben Sie nichtlineare Implementierungen des Kopierkonstruktors und des Zuweisungsoperators, es sei denn, die class kann nicht nach Wert kopiert werden

Denken Sie daran, dass das inline Schlüsselwort ein Hinweis für den Compiler ist: Der Compiler entscheidet möglicherweise, keine function zu inline zu schreiben, und kann sich dafür entscheiden, functionen zu inline zu schreiben, die nicht an erster Stelle stehen. Ich vermeide im Allgemeinen Markierungsfunktion inline (abgesehen vielleicht, wenn sehr sehr kleine functionen geschrieben werden).

Im Hinblick auf die performance ist (wie immer) die weise Vorgehensweise, die Anwendung zu profilieren, und schließlich eine Reihe von functionen, die einen Engpass darstellen.

Verweise:

  • Inline oder nicht Inline
  • [9] Inline-functionen
  • Richtlinien / Binärkompatibilitätsprobleme mit C ++
  • GotW # 33: Inline
  • Inline-Redux
  • Wirksames C ++ – Punkt 33: Vernünftig Inlining verwenden

EDIT: Bjarne Stroustrup, Die C ++ Programmiersprache:

Eine function kann als inline definiert werden. Beispielsweise:

 inline int fac(int n) { return (n < 2) ? 1 : n * fac(n-1); } 

Der inline Spezifizierer ist ein Hinweis für den Compiler, dass er versuchen sollte, Code für einen Aufruf von fac() inline zu generieren, anstatt den Code für die function einmal festzulegen und dann über den üblichen functionsaufrufmechanismus aufzurufen. Ein cleverer Compiler kann die Konstante 720 für einen Aufruf fac(6) erzeugen. Die Möglichkeit von gegenseitig rekursiven Inline-functionen, Inline-functionen, die je nach Eingabe rekursiv sind oder nicht, macht es unmöglich zu garantieren, dass jeder Aufruf einer inline function tatsächlich inline ist. Der Grad der Klugheit eines Compilers kann nicht gesetzlich festgelegt werden, so dass ein Compiler 720 , ein weiteres 6 * fac(5) und ein weiteres ein nicht-inliniertes Call fac(6) erzeugen könnte.

Um das Inlining ohne besonders raffinierte Kompilierungs- und Verknüpfungsmöglichkeiten zu ermöglichen, muss die Definition - und nicht nur die Deklaration - einer Inline-function in Reichweite sein (§9.2). Ein inline Especifier hat keinen Einfluss auf die Semantik einer function. Insbesondere hat eine Inline-function immer noch eine eindeutige Adresse und damit static Variablen (§7.1.2) einer Inline-function.

EDIT2: ISO-IEC 14882-1998, 7.1.2 functionsspezifizierer

Eine functionsdeklaration (8.3.5, 9.3, 11.4) mit einem inline Spezifizierer deklariert eine Inline-function. Der Inline-Spezifizierer zeigt der Implementierung an, dass eine Inline-Substitution des functionskörpers zum Zeitpunkt des Aufrufs dem üblichen functionsaufrufmechanismus vorzuziehen ist. Eine Implementierung ist nicht erforderlich, um diese Inline-Substitution zum Zeitpunkt des Aufrufs durchzuführen; selbst wenn diese Inline-Substitution weggelassen wird, müssen die anderen Regeln für Inline-functionen, die in 7.1.2 definiert sind, dennoch eingehalten werden.

inline hat sehr wenig mit Optimierung zu tun. inline ist eine statement an den Compiler, keinen Fehler zu erzeugen, wenn die Definition der function mehrmals im Programm auftritt und die Definition in jeder Übersetzung, die sie verwendet, auftritt und überall, wo sie erscheint, genau dieselbe Definition hat .

Angesichts der oben genannten Regeln eignet sich inline für kurze functionen, deren Körper keine zusätzlichen Abhängigkeiten über das hinaus enthalten muss, was nur eine Deklaration benötigen würde. Jedes Mal, wenn die Definition angetroffen wird, muss sie geparst werden, und Code für ihren Körper kann erzeugt werden, so dass ein gewisser Overhead des Compilers über eine function entsteht, die nur einmal in einer einzigen Quelldatei definiert ist.

Ein Compiler kann einen beliebigen functionsaufruf, den er wählt, inline (dh er ersetzt einen Aufruf der function durch Code, der diese Aktion dieser function ausführt). Es war früher so, dass es “offensichtlich” keine function inline eingliedern konnte, die nicht in derselben Übersetzungseinheit wie der Aufruf deklariert wurde, aber mit der zunehmenden Verwendung der Verbindungszeitoptimierung, selbst wenn dies jetzt nicht der Fall ist. Genauso stimmt es, dass inline markierte functionen nicht inline sind.

Wenn der Compiler angewiesen wird, eine function inline zu schreiben, ist dies eine Optimierung, und die wichtigste Regel der Optimierung ist, dass eine vorzeitige Optimierung die Wurzel allen Übels ist. Schreiben Sie immer klaren Code (mit effizienten Algorithmen), profilieren Sie Ihr Programm und optimieren Sie nur functionen, die zu lange dauern.

Wenn Sie feststellen, dass eine bestimmte function sehr kurz und einfach ist und in einer engen inneren Schleife Zehntausende Male aufgerufen wird, könnte dies ein guter Kandidat sein.

Sie werden vielleicht überrascht sein – viele C ++ Compiler werden automatisch kleine functionen für Sie inline – und sie könnten Ihre Anfrage auch ignorieren.

Vorzeitige Optimierung ist die Wurzel allen Übels!

Als Faustregel gilt, dass ich in der Regel nur “Getter” und “Setter” inline bin. Sobald der Code funktioniert und stabil ist, kann das Profiling zeigen, welche functionen vom Inlining profitieren könnten.

Auf der anderen Seite haben die meisten modernen Compiler ziemlich gute Optimierungsalgorithmen und werden Inline, was Sie inline für Sie haben sollten.

Erneut aufnehmen – Inline-One-Liner-functionen schreiben und sich später um andere kümmern.

Der beste Weg, um herauszufinden, ist Ihr Profil zu profilieren und markieren Sie kleine functionen, die oft aufgerufen werden und durch CPU-Zyklen, die inline . Das Schlüsselwort ist hier “klein” – sobald der functionsaufruf-Overhead im Vergleich zu der Zeit, die in der function verbracht wird, vernachlässigbar ist, ist es sinnlos, sie zu inline zu schreiben.

Die andere Verwendung, die ich vorschlagen würde, ist, wenn Sie kleine functionen haben, die im leistungskritischen Code oft genug aufgerufen werden, um einen Cache-Fehler relevant zu machen, sollten Sie wahrscheinlich auch diese inline. Auch dies sollte der Profiler Ihnen mitteilen können.

Inline-functionen können die Code-performance verbessern, da keine Argumente mehr in den Stapel geschoben werden müssen. Wenn sich die fragliche function in einem kritischen Teil Ihres Codes befindet, sollten Sie die Inline-Inline-Entscheidung im Optimierungsteil Ihres Projekts treffen.

Sie können mehr über Inlines in der C ++ – FAQ lesen

Ich verwende Inline-functionen oft nicht als Optimierung, sondern um den Code lesbarer zu machen. Manchmal ist der Code selbst kürzer und leichter zu verstehen als Kommentare, beschreibende Namen usw. Zum Beispiel:

 void IncreaseCount() { freeInstancesCnt++; } 

Der Leser kennt sofort die vollständige Semantik des Codes.

Ich folge im Allgemeinen einer Daumenregel, wo ich eine function mit 3-4 einfachen statementen als Inline mache. Aber es ist gut, sich daran zu erinnern, dass es nur ein Hinweis für den Compiler ist. Der letzte Aufruf, um es inline zu machen oder nicht, wird nur vom Compiler übernommen. Wenn es mehr als diese vielen statementen gibt, werde ich nicht inline deklarieren, wie bei einem dummen Compiler, es kann zu Code Bloat führen.

Der beste Weg wäre, die generierten statementen für Inline und nicht Inlined zu prüfen und zu vergleichen. Es ist jedoch immer sicher, inline wegzulassen. Die Verwendung von inline kann zu Problemen führen, die Sie nicht möchten.

Bei der Entscheidung, ob inline verwendet werden soll, behalte ich folgende Idee: Bei modernen Maschinen kann die Speicherlatenz einen größeren Engpass darstellen als bei rohen Berechnungen. Es ist bekannt, dass das Inlining von häufig aufgerufenen functionen die Größe der ausführbaren Datei erhöht. Außerdem könnte eine solche function in dem Code-Cache der CPU gespeichert werden, was die Anzahl von Cache-Misses verringert, wenn auf diesen Code zugegriffen werden muss.

Daher müssen Sie selbst entscheiden: Erhöht oder verkleinert Inlining die Größe des generierten Maschinencodes? Wie wahrscheinlich ist es, dass der Aufruf der function einen Cache-Fehler verursacht? Wenn es im gesamten Code gespickt ist, würde ich sagen, dass die Wahrscheinlichkeit hoch ist. Wenn es auf eine einzige enge Schleife beschränkt ist, ist die Wahrscheinlichkeit hoffentlich gering.

Normalerweise verwende ich Inlining in den unten aufgeführten Fällen. Wenn Sie jedoch ernsthaft an der performance interessiert sind, ist Profiling unerlässlich. Außerdem sollten Sie überprüfen, ob der Compiler den Hinweis tatsächlich übernimmt.

  • Kurze Routinen, die in einer engen Schleife aufgerufen werden.
  • Sehr einfache Accessoren (get / set) und Wrapper-functionen.
  • Template-Code in Header-Dateien erhalten leider automatisch den Inline-Hinweis.
  • Kurzcode, der wie ein Makro verwendet wird. (ZB min () / max ())
  • Kurze Mathe-Routinen.

Außerdem hat eine Inline-Methode schwerwiegende Nebenwirkungen, wenn große Projekte verwaltet werden. Wenn der Inline-Code geändert wird, werden alle Dateien, die ihn verwenden, vom Compiler automatisch neu erstellt (es ist ein guter Compiler). Dies könnte viel Entwicklungszeit kosten.

Wenn eine inline Methode in eine Quelldatei übertragen und nicht mehr inline angelegt wird, muss das gesamte Projekt neu erstellt werden (zumindest war dies meine Erfahrung). Und auch wenn Methoden in Inline konvertiert werden.

Man sollte das Inline- functions-Qualifikationsmerkmal nur verwenden, wenn der functionscode klein ist. Wenn die functionen größer sind, sollten Sie die normalen functionen bevorzugen, da das Speichern im Speicherplatz den vergleichsweise geringen Aufwand bei der Ausführungsgeschwindigkeit wert ist.

Ich habe ein paar Antworten gelesen und sehe, dass da etwas fehlt.

Die Regel, die ich verwende, ist nicht inline zu verwenden, es sei denn, ich möchte, dass es inline ist. Sieht dumm aus, jetzt Erklärung.

Compiler sind intelligent genug und kurze functionen machen immer Inline. Und macht niemals lange function als Inline, es sei denn, der Programmierer hat das gesagt.

Ich weiß, dass Inline ein Hinweis oder eine Anfrage an den Compiler ist

Eigentlich ist inline eine Reihenfolge für den Compiler, es hat keine Auswahlmöglichkeiten und nach inline Schlüsselwort wird der gesamte Code inline gemacht. Sie können also niemals inline Schlüsselwort verwenden und der Compiler wird den kürzesten Code entcasting.

Also wann inline zu verwenden?

Zu verwenden, wenn Sie Code inline haben möchten. Ich kenne nur ein Beispiel, weil ich es nur in einer Situation benutze. Es ist Benutzerauthentifizierung.

Zum Beispiel habe ich diese function:

 inline bool ValidUser(const std::string& username, const std::string& password) { //here it is quite long function } 

Egal, wie groß diese function ist, ich möchte sie inline haben, weil sie meine Software schwieriger zu knacken macht.