2010-10-13 9 views
31

Ich habe versucht, zu verstehen, was das wirklich bedeutet:Was bedeutet Inlining?

Inline-Funktion

In C++, ein Funktionselement definiert in die Klassendeklaration. (2) Eine Funktion Aufruf, dass der Compiler mit den tatsächlichen Code für die Funktion ersetzt. Das Schlüsselwort inline kann verwendet werden, um auf den Compiler hinzuweisen, um Inline Erweiterung des Körpers eines Mitglieds oder Nichtmitgliedsfunktion auszuführen. während Kompilation

inline

Um einen Funktionsaufruf mit einer Kopie der Code der Funktion zu ersetzen.

Zum Beispiel ist es so etwas wie geschrieben:

Wenn eine Methode ist endgültig, kann es inlined sein.

hier: http://www.roseindia.net/javatutorials/final_methods.shtml

Können Sie mir ein Beispiel geben oder etwas oder mir im Grunde helfen zu verstehen, was „es inlined sein kann“.

Danke.

+1

Das wird helfen: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/perf2.html#vm – codaddict

Antwort

49

Inlining ist eine Optimierung, die vom Java Just-In-Time Compiler durchgeführt wird.

Wenn Sie eine Methode:

public int addPlusOne(int a, int b) { 
    return a + b + 1; 
} 

, die Sie wie folgt aufrufen:

public void testAddPlusOne() { 
    int v1 = addPlusOne(2, 5); 
    int v2 = addPlusOne(7, 13); 

    // do something with v1, v2 
} 

der Compiler entscheidet, Ihre Funktionsaufruf mit dem Körper der Funktion zu ersetzen, so wäre das Ergebnis effektiv wie folgt aussehen:

public void testAddPlusOne() { 
    int v1 = 2 + 5 + 1; 
    int v2 = 7 + 13 + 1 

    // do something with v1, v2 
} 

Der Compiler tut dies, um den Overhead zu speichern o f macht tatsächlich einen Funktionsaufruf, bei dem jeder Parameter auf den Stack geschoben wird.

Dies kann eindeutig nur für nicht-virtuelle Funktionen durchgeführt werden. Stellen Sie sich vor, was passiert, wenn die Methode in einer Unterklasse überschrieben wird und der Typ des Objekts, das die Methode enthält, erst zur Laufzeit bekannt ist. Wie würde der Compiler wissen, welchen Code er kopieren soll: den Methodenhauptteil oder den Unterklassencode der Basisklasse Methodenkörper? Da alle Methoden in Java standardmäßig virtuell sind, können Sie diejenigen, die nicht überschrieben werden können, explizit als final markieren (oder sie in eine Klasse final setzen). Dies wird dem Compiler helfen herauszufinden, dass die Methode niemals überschrieben wird, und es ist sicher inline zu arbeiten. (Beachten Sie, dass der Compiler diese Entscheidung manchmal auch für nicht finale Methoden treffen kann.)

Beachten Sie auch das Wort Mai im Zitat. Die endgültigen Methoden sind nicht garantiert inlineable. Es gibt verschiedene Möglichkeiten, wie Sie garantieren können, dass eine Methode nicht inline sein kann, aber keine Möglichkeit, den Compiler auf zu inline zu zwingen. Es wird fast immer besser als Sie wissen, wenn Inlining hilft, oder die Geschwindigkeit des resultierenden Codes zu verletzen.

Siehe wikipedia für einen guten Überblick über Vorteile und Probleme.

+10

Gute Antwort, aber als Hinweis: Wenn Sie eine nicht-finale Methode haben, die Sie * nicht überschreiben, kann ein guter JIT das herausfinden und trotzdem inline machen. Wenn Sie dann eine Klasse laden, die sie überschreibt, kann sie das Inlining rückgängig machen. – naiad

+0

Guter Punkt, ich fügte es dem Antwortkörper hinzu. –

+0

Es ist sehr erklärend, danke für diese großartige Antwort. – Tarik

9

Angenommen, Sie haben eine Klasse, die wie folgt aussieht:

public class Demo { 
    public void method() { 
     // call printMessage 
     printMessage(); 
    } 

    public void printMessage() { 
     System.out.println("Hello World"); 
    } 
} 

Der Aufruf von printMessage könnte „inlined“ auf folgende Weise:

public class Demo { 
    public void method() { 
     // call printMessage 
     System.out.println("Hello World"); // <-- inlined 
    } 

    public void printMessage() { 
     System.out.println("Hello World"); 
    } 
} 

(Dies geschieht eigentlich nicht auf die Ebene von Java (nicht einmal auf Bytecode-Ebene), aber während JIT-Kompilierung, aber das obige Beispiel veranschaulicht das Konzept der Inlining.)

Nun überlegen, was passieren würde wenn die printMessage Methode wurde von einer anderen Klasse überlastet, wie folgt aus:

class SubDemo extends Demo { 
    public void printMessage() { 
     System.out.println("Something else"); 
    } 
} 

Nun, wenn der Compiler den Aufruf Demo.printMessage inlined es mit System.out.println("Hello World"); stecken würde, die falsch im Fall wäre, das Objekt war eigentlich ein Instanz von SubDemo.

Wenn jedoch die Methode final deklariert wurde, wäre dies unter keinen Umständen der Fall. Wenn die Methode "final" ist, bedeutet das, dass sie niemals mit einer neuen Definition überschrieben werden kann, daher ist es sicher, sie zu inline zu schreiben!

+0

Auch gute Antwort, aber als eine Notiz von einer anderen Antwort kopiert: Wenn Sie eine haben Nicht-finale Methode, die Sie nicht überschreiben, eine gute JIT kann das herausfinden und trotzdem inline machen. Wenn Sie dann eine Klasse laden, die sie überschreibt, kann sie das Inlining rückgängig machen. – naiad

+0

Es ist sehr erklärend, danke für diese großartige Antwort. – Tarik

10

Der Aufruf einer Funktion ist nicht kostenlos. Die Maschine muss einen Stapelrahmen verwalten, so dass sie zu dem aufrufenden Codeabschnitt zurückkehren kann, wenn die aufgerufene Funktion abgeschlossen ist. Das Pflegen des Stapels (einschließlich der Übergabe von Funktionsparametern auf diesem Stapel) benötigt Zeit.

Wenn eine Funktion inline ist, ersetzt der Compiler den Aufruf der Funktion durch den Code der Funktion, so dass die Leistungseinbußen eines Funktionsaufrufs zur Laufzeit vermieden werden können. Dies ist einer der klassischen Kompromisse in der Programmierung: Der Laufzeitcode wird ein wenig größer (benötigt mehr Speicher), läuft aber etwas schneller.

+0

Danke. Im ersten Absatz haben Sie wirklich recht. – Tarik