我並不十分了解編譯器和JIT優化的內部知識,但我通常會嘗試使用「常識」來猜測什麼可以優化,哪些不能。所以我在寫一個簡單的單元測試方法今天:如何編寫(測試)不會被編譯器/ JIT優化的代碼?
@Test // [Test] in C#
public void testDefaultConstructor() {
new MyObject();
}
這種方法實際上是我所需要的。它檢查默認的構造函數是否存在並且運行時沒有異常。
但後來我開始考慮編譯器/ JIT優化的影響。編譯器/ JIT可以通過完全取消new MyObject();
語句來優化此方法嗎?當然,它需要確定調用圖對其他對象沒有副作用,這是普通構造函數的典型情況,它只簡單地初始化對象的內部狀態。
我認爲只有JIT可以執行這樣的優化。這可能意味着它不是我應該擔心的事情,因爲測試方法只執行一次。我的假設是否正確?
儘管如此,我正在考慮一般的主題。當我想到如何防止這種方法被優化時,我想我可能assertTrue(new MyObject().toString() != null)
,但這非常依賴於toString()
方法的實際實現,即使如此,JIT也可以確定toString()
方法總是返回一個非null字符串(例如,如果實際上調用了Object.toString()
),並因此優化整個分支。所以這種方式是行不通的。
我知道在C#中我可以使用[MethodImpl(MethodImplOptions.NoOptimization)]
,但這不是我真正想要的。我希望找到一種(語言無關)的方式,確保我的代碼的某些特定部分能夠按照我的預期實際運行,而JIT不會干擾此過程。
此外,是否有任何典型的優化案例,我應該知道創建我的單元測試?
非常感謝!
謝謝。我想知道爲什麼JIT的行爲如此?如果一個對象分配是無用的(在某些情況下實際上可以通過靜態分析來確定),爲什麼JIT不會對它進行優化? – 2009-02-13 22:46:21
雖然我現在可以想到一個角落案例,但我認爲這很少見。如果爲了確保有足夠的內存可用於某些其他對象(甚至確保不會發生分頁)而完成對象分配,則優化將使該假定失效。 – 2009-02-13 22:48:24
需要將Java虛擬機(JVM)保持在與根據Java內存模型在JVM中執行程序代碼一致的狀態。在JIT可以證明代碼對可觀察程序狀態沒有影響的情況下,並不需要實際執行任何特定代碼或分配內存。 – 2013-05-20 20:18:38