2010-10-13 27 views
31

Próbowałem zrozumieć, co to naprawdę znaczy:Co to jest metoda inline?

inline funkcja

W C++ funkcji członka określonej w deklaracji klasy. (2) Funkcja wywołuje, że kompilator zastępuje rzeczywisty kod funkcji. Słowo kluczowe inline może być użyte do podpowiedzi do kompilatora, aby wykonać wbudowane rozszerzenie elementu lub funkcję niepodzielną .

inline

Aby zastąpić wywołanie funkcji z kopią kodu danej funkcji podczas kompilacji.

Na przykład jest napisane coś takiego:

Gdy metoda jest ostateczna, może być inlined.

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

Czy możesz dać mi przykład czy coś lub po prostu pomóc mi zrozumieć, co „może być inlined” środków.

Dzięki.

+1

To będzie pomocne: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/perf2.html#vm – codaddict

Odpowiedz

49

Inlineing to optymalizacja wykonywana przez kompilator Java Just-In-Time.

Jeśli masz metodę:

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

którą nazywamy tak:

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

    // do something with v1, v2 
} 

kompilator może zdecydować się zastąpić wywołanie funkcji z ciałem funkcji, więc wynik byłby efektywnie wyglądają tak:

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

    // do something with v1, v2 
} 

Kompilator robi to, aby zapisać obciążenie o f faktycznie wykonuje wywołanie funkcji, co wymagałoby popychania każdego parametru do stosu.

Można to wyraźnie zrobić tylko dla funkcji innych niż wirtualne. Zastanówmy się, co by się stało, gdyby metoda została przesłonięta w klasie podrzędnej, a typ obiektu zawierającego metodę nie jest znany do czasu wykonywania ... w jaki sposób kompilator wie, co kod skopiować: ciało metody klasy podstawowej lub podkategorie ciało metody? Ponieważ wszystkie metody są domyślnie wirtualne w Javie, można jawnie oznaczyć te, które nie mogą zostać zmienione jako final (lub umieścić je w klasie final). Pomoże to kompilatorowi zorientować się, że metoda nigdy nie zostanie przesłonięta i jest bezpieczna w inline. (Zauważ, że kompilator może czasami dokonać tego określenia także dla metod nieostatecznych.)

Należy również zwrócić uwagę na słowo w cytacie ze słowem. Ostateczne metody nie gwarantują, że są nieodczuwalne. Istnieją różne sposoby zagwarantowania, że ​​metoda nie może być zainicjowana, ale nie ma możliwości, aby wymusić na kompilatorze inline. Będzie prawie zawsze wiedzieć lepiej niż ty, gdy inlining pomoże vs zranić szybkość wynikowego kodu.

Aby uzyskać pełen przegląd korzyści i problemów, zobacz stronę wikipedia.

+10

Dobra odpowiedź, ale na marginesie: Jeśli masz nieostateczną metodę, którą * nie zmieniasz *, dobry JIT może ją wykombinować i mimo wszystko ją wstawić. Jeśli następnie załadujesz klasę, która go zastąpi, może cofnąć wstawianie. – naiad

+0

Dobrze, dodałem go do treści odpowiedzi. –

+0

To bardzo wyjaśniające, dziękuję za tę wspaniałą odpowiedź. – Tarik

9

Powiedzmy masz klasy, który wygląda tak:

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

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

Wezwanie do printMessage może być „inline” w następujący sposób:

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

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

(To nie jest w rzeczywistości odbywa się na poziom języka Java (nawet na poziomie kodu bajtowego), ale podczas kompilacji JIT, ale powyższy przykład ilustruje koncepcję wstawiania.)

Rozważ teraz, co by się stało Jeśli metoda printMessage została przeciążony przez inną klasę coś takiego:

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

Teraz jeśli kompilator inlined wywołanie Demo.printMessage byłoby skazani System.out.println("Hello World"); która byłaby złego w przypadku, gdy obiekt był faktycznie wystąpienie SubDemo.

Jednakże, jeżeli metoda została zadeklarowana jako final, w żadnym wypadku nie jest to prawdą. Jeśli metoda jest "ostateczna", oznacza to, że nigdy nie można jej zastąpić nową definicją, dlatego można ją bezpiecznie zainicjować!

+0

Dobra odpowiedź, ale jako notatka skopiowana z innej odpowiedzi: Jeśli masz nieostateczna metoda, której nie zastąpisz, dobry JIT może to wykombinować i zainspirować. Jeśli następnie załadujesz klasę, która go zastąpi, może cofnąć wstawianie. – naiad

+0

To bardzo wyjaśniające, dziękuję za tę wspaniałą odpowiedź. – Tarik

10

Wywołanie funkcji nie jest bezpłatne. Maszyna musi utrzymywać ramkę stosu, aby mogła powrócić do sekcji wywołującej kod po zakończeniu wywoływanej funkcji. Utrzymanie stosu (w tym przekazywanie parametrów funkcji na tym stosie) wymaga czasu.

Po włączeniu funkcji kompilator zamienia wywołanie funkcji na kod funkcji, dzięki czemu można uniknąć kary za wydajność wywołania funkcji w czasie wykonywania. Jest to jedna z klasycznych kompromisów w programowaniu: kod wykonawczy staje się trochę większy (zajmuje więcej pamięci), ale działa trochę szybciej.

+0

Dzięki. W pierwszym akapicie masz rację. – Tarik