4

我對VM在運行時的優化以及編譯時感興趣。我有這樣的想法,即在編譯時優化是最高效和最簡單的。無法理解關於編譯器優化的說法

但是,在某些情況下,我的想法似乎是錯誤的。這是顯而易見的Steve Yeggie's statement quoted by Daniel

當在運行時通過一個聰明 虛擬機執行的[O] ptimization往往更容易 - - 。

爲什麼在運行時由VM比在編譯時執行優化更容易?

+2

我認爲Steve Yeggie的意思是「更容易得到更好的結果」,而不是「更容易做到」,這是我認爲你是在解釋它。畢竟,我認爲重新編排程序比編譯時更難以執行。 – Pod 2009-06-26 10:49:35

回答

4

簡短回答:因爲它更容易在運行時識別和分析熱點 - 程序中使用最多時間的部分。

龍答:

如果你開始運行在解釋模式下的代碼虛擬機可以算多久多久代碼的不同部分使用。這些部件可以更好地優化。

採取嵌套的if-then-else-clause。較少的布爾檢查需要較少的運行時間。如果優化零件的路徑(更經常執行),則可以獲得更好的整體運行時間。另一點是,在運行時你可以做出假設,這在編譯時是不可能的。 Java-VM例如在服務器模式虛擬方法中內聯 - 只要加載一個類即可實現這些方法。如果在編譯時完成這將是不安全的。如果另一個類被加載,JVM會再次優化代碼,但這種情況通常不會發生。

另外在運行時更知道程序運行的機器。如果你有一臺擁有更多寄存器的機器,你可以使用它們。再一次,如果在編譯時完成這是不安全的。

有一點要說的是:在運行時優化也有缺點。最重要的是:優化的時間被添加到程序的運行時間。而且它更復雜,因爲你必須編譯程序的一部分並執行它們。虛擬機中的錯誤至關重要。想想編譯器,有時會崩潰 - 你可以重新編譯,一切都很好。如果虛擬機有時會崩潰,這意味着您的程序有時會崩潰。不好。

結論:您可以在運行時進行每次優化,這在編譯時是可能的......還有一些更多。您有關於程序的更多信息,它是執行路徑和程序運行的機器。但是你必須考慮運行優化所需的時間。在運行時執行也比較複雜,而且錯誤比編譯時更重要。

+2

「你可以在編譯時在運行時進行每次優化」 - 我不相信它。簡檔引導的優化器可以重新排列對象中數據成員的順序,例如,以改善引用的局部性或移動最常用的對象來抵消0.如果在內存中已經有實際的對象,那幾乎是不可能的。 – MSalters 2009-06-26 11:08:13

+0

現代垃圾收集器一直在內存中重新排列對象以減少碎片。爲此,必須重寫所有引用/指針(或者使用一些聰明的間接引用)。重新安排數據成員在這方面看起來並不複雜。但我不得不承認,我不知道一個虛擬機的實例。 – Mnementh 2009-06-26 11:12:36

1

因爲在運行時你有額外的信息:機器如何執行,你的進程的內存限制,可能最重要的是,什麼代碼正在執行和多久。

這些東西允許您進行運行時優化,而這些優化在編譯時無法完成。

2

因爲在運行時有更多的信息可用。例如,確切的CPU,操作系統和其他環境細節是已知的。該信息對優化應該如何完成有影響。

2

虛擬機具有完整的程序代碼,編譯器通常只有部分代碼,因爲不同的翻譯單元單獨翻譯。因此VM有更多的數據用於分析。

1

虛擬機可以收集統計信息以進行優化,同樣數據庫也會對您的使用情況進行優化。

1

連續保存統計信息和檢查不變量也會影響編譯或解釋片段的執行時間。如果你無法做到快速優化,請不要打擾。我認爲在運行時間而不是編譯時間的情況下獲得更好的結果並不容易。考慮到良好實施的複雜性,我認爲這更加困難。如同足夠好的優化編譯器產生比人類更好的裝配的常見誤解,足夠聰明的虛擬機可能需要該死的太聰明以至於無法更快執行。

0

需要認識到的一點是,它不是允許運行時優化的虛擬機的概念,而是許多虛擬機不會丟棄原始程序元數據並且內置反射功能。一個更合適的術語是「運行時庫」可以比靜態優化單獨做更好的優化;這適用於非VM語言,如C.