Esistono funzioni inline in java?


112

Esiste un concetto di funzioni inline in java o ha sostituito qualcos'altro? Se c'è, come si usa? Ho sentito dire che public, statice finalmetodi sono le funzioni inline. Possiamo creare la nostra funzione inline?



3
Come commento minore, l'ottimizzazione prematura è la radice di tutti i mali. Senza comprendere appieno la natura di pubblico, statico e finale non puoi davvero capire l'impatto che potrebbe avere l'inlining, e questo dipende dalla JVM che stai utilizzando. Assicurati di rispondere prima al motivo per cui devi incorporare qualcosa: è quasi certo che ci sono ottimizzazioni del ROI più elevate che puoi fare altrove.
Nathaniel Ford,

Risposte:


123

In Java, le ottimizzazioni vengono solitamente eseguite a livello di JVM. In fase di esecuzione, la JVM esegue alcune analisi "complicate" per determinare i metodi da incorporare. Può essere aggressivo nell'inlining e Hotspot JVM può effettivamente incorporare metodi non finali.

I compilatori Java non incorporano quasi mai alcuna chiamata al metodo (la JVM fa tutto questo in fase di esecuzione). Fanno inline costanti di tempo di compilazione (es. Valori primitivi statici finali). Ma non metodi.

Per più risorse:

  1. Articolo: Java HotSpot Performance Engine: esempio di integrazione dei metodi

  2. Wiki: Inlining in OpenJDK , non completamente popolato ma contiene collegamenti a discussioni utili.


15

No, non esiste una funzione inline in java. Sì, puoi usare un metodo statico pubblico ovunque nel codice quando inserito in una classe pubblica. Il compilatore Java può eseguire l'espansione in linea su un metodo statico o finale, ma ciò non è garantito.

Tipicamente, tali ottimizzazioni del codice vengono eseguite dal compilatore in combinazione con JVM / JIT / HotSpot per i segmenti di codice utilizzati molto spesso. Anche altri concetti di ottimizzazione come la dichiarazione di registro dei parametri non sono noti in java.

Le ottimizzazioni non possono essere forzate tramite dichiarazione in java, ma eseguite dal compilatore e da JIT. In molti altri linguaggi queste dichiarazioni sono spesso solo suggerimenti per il compilatore (è possibile dichiarare più parametri di registro di quanti ne abbia il processore, il resto viene ignorato).

La dichiarazione di metodi java statici, finali o privati ​​sono anche suggerimenti per il compilatore. Dovresti usarlo, ma nessuna garanzia. Le prestazioni di Java sono dinamiche, non statiche. La prima chiamata a un sistema è sempre lenta a causa del caricamento della classe. Le chiamate successive sono più veloci, ma a seconda della memoria e del runtime le chiamate più comuni sono ottimizzate nel sistema in esecuzione, quindi un server potrebbe diventare più veloce durante il runtime!


3
finalnon hanno alcun impatto sull'inlining di JIT
Steve Kuo

1
+1, Ma come possiamo verificare se la versione compilata di un metodo è inline?
Pacerier

@Pacerier Ma perché dovremmo verificare se qualcosa è inline?
Arne Burmeister

14

Java non fornisce un modo per suggerire manualmente che un metodo deve essere inline. Come dice @notnoop nei commenti, l'inlining viene in genere eseguito dalla JVM al momento dell'esecuzione.


3
La maggior parte dei compilatori java non effettua mai chiamate di metodo inline. Per lo più la JVM lo fa.
notnoop

Grazie per averlo chiarito. Non ero sicuro in quale fase fosse esattamente successo. Modificherò il mio post per riflettere questo.
Thomas Owens

@ThomasOwens lo fa, ma non è pubblicojdk.internal.vm.annotation.ForceInline
Eugene

4

Quello che hai detto sopra è corretto. A volte i metodi finali vengono creati come inline, ma non c'è altro modo per creare esplicitamente una funzione inline in java.


5
Non è garantito che i metodi finali siano in linea.
Thomas Owens

4
Su HotSpot, l'aggiunta finalnon fa alcuna differenza sul fatto che il metodo sia inline o meno.
Tom Hawtin - tackline

4
@Thomas - motivo per cui ho detto "A volte metodi finali ..."
GreenieMeanie

@ TomHawtin-tackline hai una fonte autorevole per questo? Per quanto ne so, i metodi finali possono essere inline senza impiegare un type guard, il che significa che il modificatore rende l'inlining del metodo più efficiente che senza il modificatore. So che Jikes RVM ne tiene conto quando decide se inline. Sei sicuro che HotSpot non faccia qualcosa di simile?
Jannik Jochem

2

Esempio di vita reale:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

Quindi in altre classi, posso uscire se il codice è scaduto. Se faccio riferimento alla variabile EXPIRED_ON di un'altra classe, la costante è in linea al codice byte, rendendo molto difficile rintracciare tutte le posizioni nel codice che controlla la data di scadenza. Tuttavia, se le altre classi invocano il metodo isExpired (), viene chiamato il metodo effettivo, il che significa che un hacker potrebbe sostituire il metodo isExpired con un altro che restituisce sempre false.

Sono d'accordo che sarebbe molto bello forzare un compilatore a incorporare il metodo finale statico a tutte le classi che lo fanno riferimento. In tal caso, non è necessario nemmeno includere la classe Control, poiché non sarebbe necessaria in fase di esecuzione.

Dalla mia ricerca, questo non può essere fatto. Forse alcuni strumenti di Obfuscator possono farlo, oppure potresti modificare il tuo processo di compilazione per modificare i sorgenti prima della compilazione.

Per quanto riguarda la prova se il metodo dalla classe di controllo è inserito in linea in un'altra classe durante la compilazione, provare a eseguire l'altra classe senza la classe Control nel classpath.


2

Bene, ci sono metodi che possono essere chiamati metodi "inline" in java, ma a seconda della jvm. Dopo la compilazione, se il codice macchina del metodo è inferiore a 35 byte, verrà trasferito immediatamente a un metodo inline, se il codice macchina del metodo è inferiore a 325 byte, potrebbe essere trasferito in un metodo inline, a seconda della jvm.


1
Questi sono i valori predefiniti per la VM di Oracle, vedere docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

quindi, sembra che non ci sia, ma puoi usare questa soluzione alternativa usando guava o un'implementazione della classe Function equivalente, perché quella classe è estremamente semplice, es .:

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

sì, questo è un codice morto solo per esemplificare come creare un blocco di codice complesso (all'interno di {}) per fare qualcosa di così specifico che non dovrebbe preoccuparci di creare alcun metodo per esso, AKA inline!


Sembra un'idea ragionevole. Hai una versione di questo che non utilizza le librerie comuni di Google?
ragerdl

0

Java9 ha un compilatore "Ahead of time" che esegue diverse ottimizzazioni in fase di compilazione, piuttosto che in runtime, che può essere visto come inlining.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.