2013-06-19 47 views
1

我打算編寫一個針對.NET平臺的編程語言,這讓我開始考慮定位這種平臺的代碼生成方面。我是寫編譯器的新手,但是我知道在編譯(或者可以)的階段中已經完成了優化。我開始懷疑花費時間優化輸出(在這種情況下CIL,但這也適用於JVM),因爲JIT編譯器和諸如JVM的HotSpot之類的東西可以在運行時進行優化。由於JIT已經優化,因此在針對.NET或JVM時優化生成的代碼(CIL或JVM等價物)會有什麼好處嗎?當代碼生成針對帶JIT的運行時時,是否需要進行優化?

回答

5

這取決於。有無數的優化。任何給定的編譯器(您的編譯器,JIT編譯器或任何其他編譯器)必須僅實現這些編譯器的一部分。這種選擇取決於可用時間,典型/預期輸入代碼,優先級等,因此構建JIT編譯器的工程師可能選擇了適合他們期望的程序的優化,但對於那些程序來說不太適合關心。

您將必須確定JIT編譯器錯過了哪些優化。當然,這樣做的方式是經驗性的:實際上編寫程序,讓JIT編譯器優化它們(確保正確執行此部分 - 禁用調試,編譯發佈,選擇實際基準等),然後檢查最終的機器碼。尋找意想不到的代碼(當然,您需要大會知識),並確定它是否是錯過的優化,或者JIT是否比您想象的更聰明。

如果是錯過了優化,你有另外一個問題:你不能輸出你想要的機器代碼,你必須產生不同的IL代替。 由於VM不知道的語言特徵(例如JVM上的多種方法),未實現的優化是可能是。您在編譯過程中將其降到了虛擬機的條款中,但您選擇的翻譯並不適合JIT的合格順序,啓發式等。 由於您不能自己輸出機器代碼,您現在必須找到一個替代IL片段對於相同的輸入語言代碼。理想情況下,JIT編譯器處理得很好。發現這可能是想象力的鍛鍊,但這在技術上並不難,只是猜測與基準測試交錯。另一個答案指出,JIT編譯器在時間限制下工作。這可能導致的優化可能發生被錯過(如常量傳播的時間不多了),但隨着JIT編譯器的創造者面臨着同樣的問題,這可能不是太嚴重,如果你不創建太多大/更復雜的代碼。 如果您創建了JIT編譯器無法修復的代碼,那麼您必須在AOT編譯器中複製它的優化。我不認爲這是一個可能的情況,即使發生這種情況,即使非常簡單的優化也應該能夠解決這個問題。

所以,在總結:首先得有個簡單的翻譯,然後尋找錯過的優化,要麼使其更容易優化的JIT編譯器,或者自己做(如果可能的話 - 自適應優化是更難在AOT設置)。

+0

非常感謝您的回答。這很有道理。 – Jetti

1

通常,JIT編譯器有一些閾值來控制他們將嘗試執行多少優化。這些可能基於方法的IL的大小和/或已經花費JIT編譯該方法的時間量。所以是的,IL已經被優化可能受益於進一步的JIT優化。與往常一樣,需要權衡:您希望將多少時間添加到您的編譯器(以及測試/維護它們),還是將代碼編譯爲JIT的速度以及優化級別。

改進的程度在很大程度上取決於AOT優化的IL相對於未優化的IL以及控制JIT編譯器的閾值(至少對於Microsoft CLR而言,並不廣爲人知)。找出答案的唯一方法是自己做一些測試。

2

我覺得這個問題很難回答。

例如,F#編譯器執行tail call optimization,因爲在該語言中使用尾遞歸函數是很常見的,所以F#編譯器在某些情況下可以比JIT編譯器和某些版本的JIT更好地優化它們編譯器根本不執行優化。

因此,您的語言可能有一些常見的操作,其直接執行不會很好。在這種情況下,發出優化的IL代碼是有意義的。

我認爲你應該做的和你在編寫普通程序時一樣:首先用一種簡單易讀的方式編寫代碼。只有當某些事情表現不佳時,纔會嘗試優化。可能值得考慮的是,將來可能需要進行一些優化,並使代碼足夠模塊化,以便由於某種優化而不必重寫一半。但現在,這應該夠了。

編寫一個編譯器已經夠用了(即使你的目標是IL)。先完成並稍後考慮優化。

+0

感謝您的回覆。你在關於特定於語言的優化中提出了一個很好的觀點,這在JIT中是不會做的,這絕對是我沒有想到的。 – Jetti

相關問題