Was stimmt nicht mit Inline-Funktionen?
-
09-06-2019 - |
Frage
Während wäre es sehr praktisch sein, um Inline-Funktionen in einigen Situationen zu verwenden,
Gibt es irgendwelche Nachteile, die mit Inline-Funktionen?
Fazit :
Offenbar Es ist nichts falsch mit Inline-Funktionen.
Aber es ist erwähnenswert, die folgenden Punkte!
-
Übermäßiger Einsatz von inlining kann tatsächlich langsame Programme. Je nach Größe einer Funktion, inlining es die Codegröße kann dazu führen, zu erhöhen oder zu verringern. eine sehr kleine Accessorfunktion inlining wird in der Regel Codegröße verringern, während eine sehr große Funktion inlining dramatisch Codegröße erhöhen. Bei modernen Prozessoren in der Regel kleiner Code läuft schneller durch bessere Nutzung des Befehls-Cache. - Google-Richtlinien
-
Die Geschwindigkeit Vorteile der Inline-Funktionen sind in der Regel zu verringern, weil die Funktion in der Größe wächst. An einem gewissen Punkt der Aufwand für den Funktionsaufruf an die Ausführung des Funktionskörpers im Vergleich klein wird, und der Nutzen verloren - Quelle
-
Es gibt nur wenige Situationen, in denen eine Inline-Funktion nicht funktionieren kann:
- Für eine Funktionswerte der Rückkehr; wenn eine return-Anweisung vorhanden ist.
- Für eine Funktion keine Werte zurückgegeben werden; Wenn eine Schleife, Schalter oder goto-Anweisung existiert.
- Wenn eine Funktion rekursiv ist. -Quelle
-
Das
__inline
Schlüsselwort bewirkt nur eine Funktion zu inlined, wenn Sie die Option zum Optimieren angeben. Wenn optimize angegeben wird, ob oder ob nicht__inline
fühlte sich geehrt, hängt von der Einstellung der Inline-Optimierer Option. Standardmäßig ist die Inline-Option wirksam, wenn das Optimierungsprogramm ausgeführt wird. Wenn Sie optimize angeben, müssen Sie auch die noinline Option angeben, wenn Sie das__inline
Schlüsselwort ignoriert werden soll. -Quelle
Lösung
Es sollte darauf hingewiesen werden, dass das Inline-Schlüsselwort an den Compiler eigentlich nur ein Hinweis ist. Der Compiler kann die Inline ignorieren und einfach Code für die Funktion irgendwo erzeugen.
Der Hauptnachteil Funktionen Inline ist, dass es die Größe der ausführbaren Datei erhöhen (abhängig von der Anzahl der Instanziierungen). Dies kann ein Problem auf einigen Plattformen (zB. Eingebettete Systeme), vor allem, wenn die Funktion selbst rekursiv ist.
Ich würde auch machen inline'd Funktionen empfehlen sehr klein - Die Geschwindigkeitsvorteile von Inline-Funktionen sind in der Regel zu verringern, weil die Funktion in der Größe wächst. An einem gewissen Punkt der Overhead des Funktionsaufrufes wird an die Ausführung des Funktionskörpers klein im Vergleich, und der Nutzen verloren.
Andere Tipps
Es könnte die Größe der Erhöhung ausführbare Datei, und ich glaube nicht, Compiler wird immer tatsächlich machen sie inline, obwohl Sie das verwendete Inline-Schlüsselwort. (Oder ist es die andere Art und Weise um, wie das, was Vaibhav sagt? ...)
Ich denke, es ist in der Regel in Ordnung, wenn die Funktion hat nur 1 oder 2 Aussagen.
Edit: Hier ist, was die Linux Coding Dokument sagt über sie:
Kapitel 15: Die Inline-Krankheit
Es scheint eine gemeinsame zu sein misperception dass gcc hat einen Zauber „Machen mich schneller“ Speedup Option genannt "in der Reihe". Während die Verwendung von inlines kann angebracht sein (zum Beispiel als Mittel von Makros zu ersetzen, siehe Kapitel 12), es ist sehr oft nicht. Reichliche Verwendung von das Inline-Schlüsselwort führt zu einem viel größeren Kernel, was wiederum verlangsamt sich die System als Ganzes nach unten, aufgrund einer größer icache Stellfläche für die CPU und nur weil es weniger Speicher für den Pagecache. Man denke nur an sie; ein Pagecache-Fehl Ursachen suchen eine Platte, die leicht nimmt 5 Millisekunden. Es gibt eine Menge CPU Zyklen, die in diese gehen kann 5 miliseconds.
Eine vernünftige Faustregel nicht setzen Inline an Funktionen, die mehr als 3 Zeilen Code in ihnen. Ein Ausnahme von dieser Regel sind die Fälle, wobei ein Parameter ist bekannt, ein sein compiletime konstant, und als Ergebnis dieser Durchgängigkeit Sie wissen die Compiler wird in der Lage sein, die meisten zu optimieren Ihre Funktion kompiliert weg zur Zeit. Für ein gutes Beispiel für diesen letzteren Fall siehe kmalloc () Inline-Funktion.
Oft Leute argumentieren, dass Inline-Zugabe auf Funktionen, die statische und verwendet werden, sind nur ein einziges Mal ist immer ein Gewinn, da es ist kein Raum Kompromiss. Dies ist zwar technisch korrekt ist gcc fähig inlining diese automatisch ohne helfen, und die Wartung Thema Entfernen des Inline-, wenn ein zweiter Benutzer erscheint größer als der möglichen Wert der Hinweis, dass gcc sagt zu tun etwas, das es ohnehin getan hätte.
Ich stimme mit den anderen Beiträgen:
- Inline kann überflüssig sein, da der Compiler wird es tun
- inline kann Ihren Code aufblasen
Ein dritter Punkt ist es Sie zwingen kann Implementierungsdetails in Ihrem Header, .e.g zu belichten.
class OtherObject;
class Object {
public:
void someFunc(OtherObject& otherObj) {
otherObj.doIt(); // Yikes requires OtherObj declaration!
}
};
Ohne die Inline eine Vorwärtserklärung OtherObject alles war man braucht. Mit dem Inline Ihrer Header muss die Definition für OtherObject.
Wie andere erwähnt haben, das Inline-Schlüsselwort ist nur ein Hinweis an den Compiler. In der Tat werden die meisten modernen Compiler vollständig diesen Hinweis ignorieren. Der Compiler hat seine eigene Heuristik, um zu entscheiden, ob eine Funktion inline, und ehrlich gesagt will nicht Ihren Rat, ich danke Ihnen sehr.
Wenn Sie wirklich, wirklich etwas Inline machen wollen, wenn Sie es tatsächlich profiliert haben und schaute auf die Demontage, um sicherzustellen, dass der Compiler heuristische zwingende Sinn tatsächlich macht, dann ist es möglich:
- In VC ++, verwenden Sie das Schlüsselwort __forceinline
- In GCC, verwenden __attribute __ ((always_inline))
Das Schlüsselwort inline hat einen zweiten gültigen Zweck jedoch - deklarieren Funktionen in Header-Dateien, aber nicht innerhalb einer Klassendefinition. Das Inline-Schlüsselwort wird benötigt, um den Compiler zu sagen, nicht mehr Definitionen der Funktion zu erzeugen.
Es gibt ein Problem mit Inline - sobald Sie eine Funktion in einer Header-Datei definiert (die Inline bedeutet, entweder explizit oder implizit durch einen Körper eines Mitglied Funktion innerhalb der Klasse definiert wird) gibt es keine einfache Möglichkeit, es zu ändern, ohne zu zwingen Sie Ihre Benutzer neu zu kompilieren (als Gegensatz zu relink). Oft führt dies zu Problemen, vor allem, wenn die betreffenden Funktion in einer Bibliothek definiert und Header ist Teil seiner Oberfläche.
Ich bezweifle es. Auch der Compiler inlines automatisch einige Funktionen für die Optimierung.
Ich weiß nicht, ob meine Antwort ist im Zusammenhang mit der Frage, aber:
Seien Sie sehr vorsichtig über Inline virtuelle Methoden! Einige Buggy-Compiler (frühere Versionen von Visual C ++ zum Beispiel) würde für virtuelle Methoden Inline-Code generieren, wo das Standardverhalten, sondern gehen Sie die Vererbungsbaum und rufen Sie die entsprechende Methode nichts zu tun war.
Inlining größere Funktionen kann das Programm größer, was zu mehr Cache-Misses machen und machen es langsamer.
Die Entscheidung, wann eine Funktion klein genug ist, dass inlining die Leistung zu erhöhen, ist ziemlich schwierig. Googles C ++ Style Guide empfiehlt nur inlining Funktionen von 10 Linien oder weniger.
Sie sollten auch beachten, dass das Inline-Schlüsselwort ist nur eine Anfrage. Der Compiler kann wählen, es nicht inline, ebenfalls kann der Compiler wählen, um eine Funktion inline zu machen, dass Sie nicht als Inline definiert haben, wenn sie die Geschwindigkeit / Größe Kompromiss ist es wert denken.
Diese Entscheidung generaly basierte auf einer Reihe von Dingen gemacht wird, wie die Einstellung zwischen optimize für Geschwindigkeit (vermeidet die Anruffunktion) und optimiert für Größe (inlining Code aufblähen verursachen kann, so ist nicht groß für große wiederholt verwendete Funktionen ).
mit dem VC ++ Compiler Sie diese Entscheidung durch die Verwendung __forceinline
overide können
SO im Allgemeinen: Verwenden Sie inline, wenn Sie wirklich eine Funktion in einem Header haben wollen, aber an anderer Stelle Theres wenig Sinn, denn wenn Ihr etwas davon profitieren würde, wird ein guter Compiler es trotzdem für Sie inline machen werden.
Übermäßige inlining von Funktionen können Größe von kompilierten ausführbaren erhöhen, die negative Auswirkungen auf die Cache-Leistung haben, aber heute entscheiden Compiler über Funktion inlining auf ihren eigenen (je nach vielen Kriterien) und Inline-Schlüsselwort zu ignorieren.
Unter anderem mit Inline-Funktionen, die ich stark überstrapazieren gesehen habe (ich habe von 500 Zeilen Inline-Funktionen zu sehen), was Ihnen bewusst sein müssen, sind:
-
bauen Instabilität
- Ändern der Quelle einer Inline-Funktion bewirkt, dass alle Benutzer des Headers neu kompilieren
-
#include
s Leck in den Client. Dies kann sehr böse sein, wenn Sie eine Inline-Funktion überarbeiten und einen nicht-mehr verwendet Header entfernen, die hat einige Client verlassen.
-
Größe der ausführbaren Datei
- Jedes Mal, wenn ein Inline anstelle eines Call-Befehl inlined wird der Compiler den gesamten Code des Inline erzeugen muss. Das ist in Ordnung, wenn der Code der Funktion kurz ist (eine oder zwei Linien), nicht so gut, wenn die Funktion lang
- Einige Funktionen können viel mehr Code als auf den ersten Blick erscheint erzeugen. Ich typischen Fall ist ein ‚trivial‘ destructor einer Klasse, die eine Menge von nicht-pod Elementvariablen (oder zwei oder drei Elementvariablen mit eher chaotisch Destruktoren) hat. Ein Anruf hat für jeder destructor erzeugt werden.
-
Ausführungszeit
- das ist sehr abhängig von der CPU-Cache und gemeinsam genutzte Bibliotheken, sondern Referenzlokalität ist wichtig. Wenn der Code, der Sie inlining sein könntest geschieht in einem Ort in CPU-Cache gehalten werden, eine Anzahl von Clients kann den Code findet eine nicht von einer Cache-Miss leiden und die nachfolgenden Speicher holen (und schlimmer noch, soll es passieren, eine Platte holen) . Leider ist dies einer jener Fälle, in denen Sie wirklich brauchen, Performance-Analyse zu tun.
Der Codierungsstandard, wo ich Grenze Inline-Funktionen auf einfachen Setter / Getter arbeiten, und zwar sage Destruktoren nicht inline sein sollten, es sei denn, Sie Performance-Messungen haben den inlining zu zeigen, verleiht einen spürbaren Vorteil.
-
Wie andere Leute schon gesagt, dass Inline-Funktion ein Problem, wenn der der Code large.As ist jede Anweisung in einem bestimmten Speicherplatz gespeichert ist erstellen kann, so die Inline-Funktion Überlastung einen Codes macht mehr Zeit in Anspruch nehmen zu bekommen exicuted .
-
Es gibt nur wenige andere Situationen, in denen Inline möglicherweise nicht
- funktioniert nicht bei rekursiven Funktion.
- Es kann auch nicht mit statischen Variablen arbeiten.
- es dort auch nicht im Falle arbeiten Verwendung einer Schleife ist, schalten etc.or wir, dass mit mehreren Anweisungen sagen kann.
- Und die Funktion Haupt kann nicht als Inline-Funktion arbeiten.