Sulla base delle discussioni relative a una risposta alla domanda this, ho scoperto un comportamento davvero strano dell'ottimizzatore di Java Hotspot. Il comportamento osservato può essere visto almeno in Oracle VM 1.7.0_17, ma sembra che si verifichino anche nelle versioni precedenti di Java 6.Strano comportamento dell'ottimizzatore del ciclo dell'hotspot
Prima di tutto, ero già a conoscenza dell'ottimizzatore, ovviamente consapevole del fatto che alcuni metodi nell'API standard sono invarianti e non hanno effetti collaterali. Quando si esegue un ciclo come double x=0.5; for(double d = 0; d < Math.sin(x); d += 0.001);
, l'espressione Math.sin(x)
non viene valutata per ogni iterazione, ma l'ottimizzatore è consapevole del fatto che il metodo non ha effetti collaterali rilevanti e che il risultato è invariato, purché x
non venga modificato nel ciclo.
Ora ho notato che cambiare semplicemente x
da 0,5 a 1,0 disabilitato questa ottimizzazione. Ulteriori test indicano che l'ottimizzazione è abilitata solo se abs (x) < asin (1/sqrt (2)). C'è una buona ragione per quello, che non vedo, o è una limitazione inutile alle condizioni ottimizzanti?
Edit: L'ottimizzazione sembrano essere implementato in hotspot/src/share/vm/opto/subnode.cpp
Come fai a sapere che "l'espressione Math.sin (x) non viene valutata per ogni iterazione"?Hai guardato il codice assembly? O tempo misurato? Si noti inoltre che 'Math.sin' è un metodo intrinseco in Java 1.7 (probabilmente prima) quindi il codice eseguito non è il codice Java mostrato nel sorgente JDK ... – assylias
@assylias: Misurando il tempo, ma si ha un buon punto . Mi chiedo se sia l'effettiva implementazione di Math.sin, che è ottimizzata per gli argomenti
jarnbjo
@jarbjo L'implementazione per cpus x86_64 è qui: http://hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/6e9aa487055f/src/cpu/x86/vm/stubGenerator_x86_64.cpp intorno alla riga 2878. – assylias