2012-08-29 41 views
1

我們正在構建一個用於對Java字節代碼程序進行平均情況運行時分析的工具。其中一部分是測量實際運行時間。因此,我們將採取任意的,用戶提供的方法,其可以或可以不具有一個結果,並且可以或可以不具有副作用(實例包括快速排序,階乘,虛設嵌套循環,...)和執行它(使用反射),測量經過的時間。 (無論我們是否正確基準所有是除了點這裏)。JIT可以防止優化方法調用嗎?

在基準測試代碼,顯然,我們不這樣做,結果什麼(有些方法甚至不會有結果)。因此,不知道JIT可能做什麼,事實上我們已經發現,它似乎有時會優化整個基準方法。由於基準測試方法在現實中並未單獨使用,因此會導致基準測試無效。

我們怎樣才能防止JIT做那?我們不想把它完全關閉,因爲那時標杆需要年齡,我們希望標杆「真正的」運行時無論如何(所以我們要JIT是積極的方法)。

我知道this question,但給定的情景過於狹窄;我們不知道結果類型(如果有的話),因此不能以某種方式使用結果JIT不會看到無用的結果類型。

+0

使用結果。 –

+1

可惜,這從來沒有得到真正的答案。 +1爲「爲什麼我必須在許多評論中重新解釋我的問題」綜合症的團結。 – sqykly

回答

1

簡單的解決辦法是寫一個更現實的基準,這確實有用差不多的東西,這樣就不會被優化掉。

有一些竅門來迷惑JIT的,但這些都不可能幫助你。

下面是示例的,其中該方法是通過反射,MethodHandle叫和編譯以什麼基準的。

import java.lang.invoke.*; 
import java.lang.reflect.*; 

public class Main { 
    public static void main(String... args) throws Throwable { 
     for (int j = 0; j < 5; j++) { 
      testViaReflection(); 
      testViaMethodHandle(); 
      testWithoutReflection(); 
     } 
    } 

    private static void testViaReflection() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { 
     Method nothing = Main.class.getDeclaredMethod("nothing"); 
     int runs = 10000000; // triggers a warmup. 
     long start = System.nanoTime(); 
     Object[] args = new Object[0]; 
     for (int i = 0; i < runs; i++) 
      nothing.invoke(null, args); 
     long time = System.nanoTime() - start; 
     System.out.printf("A call to %s took an average of %.1f ns using reflection%n", nothing.getName(), 1.0 * time/runs); 
    } 

    private static void testViaMethodHandle() throws Throwable { 
     MethodHandle nothing = MethodHandles.lookup().unreflect(Main.class.getDeclaredMethod("nothing")); 
     int runs = 10000000; // triggers a warmup. 
     long start = System.nanoTime(); 
     for (int i = 0; i < runs; i++) { 
      nothing.invokeExact(); 
     } 
     long time = System.nanoTime() - start; 
     System.out.printf("A call to %s took an average of %.1f ns using MethodHandle%n", "nothing", 1.0 * time/runs); 
    } 

    private static void testWithoutReflection() { 
     int runs = 10000000; // triggers a warmup. 
     long start = System.nanoTime(); 
     for (int i = 0; i < runs; i++) 
      nothing(); 
     long time = System.nanoTime() - start; 
     System.out.printf("A call to %s took an average of %.1f ns without reflection%n", "nothing", 1.0 * time/runs); 
    } 

    public static void nothing() { 
     // does nothing. 
    } 
} 

打印

A call to nothing took an average of 6.6 ns using reflection 
A call to nothing took an average of 10.7 ns using MethodHandle 
A call to nothing took an average of 0.4 ns without reflection 
A call to nothing took an average of 4.5 ns using reflection 
A call to nothing took an average of 9.1 ns using MethodHandle 
A call to nothing took an average of 0.0 ns without reflection 
A call to nothing took an average of 4.3 ns using reflection 
A call to nothing took an average of 8.8 ns using MethodHandle 
A call to nothing took an average of 0.0 ns without reflection 
A call to nothing took an average of 5.4 ns using reflection 
A call to nothing took an average of 13.2 ns using MethodHandle 
A call to nothing took an average of 0.0 ns without reflection 
A call to nothing took an average of 4.9 ns using reflection 
A call to nothing took an average of 8.7 ns using MethodHandle 
A call to nothing took an average of 0.0 ns without reflection 

我曾以爲MethodHandles比反射快,但它不會出現如此。

+0

我該怎麼做,不知道基準代碼? – Raphael

+0

即使你知道你正在嘗試進行基準測試,它很難理解結果的含義。我不確定你想要達到什麼。 –

+0

我們得到了一些方法(來自用戶),並且想要分別計算給定輸入集的運行時間。因此,基準代碼必須是通用的(對給定的方法幾乎沒有限制)。我們對JIT優化內部*方法(事實上,我們希望它)很好,但在某些情況下,JIT會優化整個方法。這個問題不清楚,我應該編輯嗎? – Raphael

1

我不相信有任何的方式來選擇性地禁用JIT優化,除了一些實驗值(如逃生分析)。

你這樣說:

我們不想把它完全關閉,因爲那時標杆需要年齡,我們希望標杆「真實」的運行時間反正。

但你是什麼試圖做的恰恰是。在實際運行時,方法調用被內聯,如果他們沒有做任何事情的被優化掉。所以通過禁止這些優化,您可以獲得與實際程序中實際發生的不匹配的方法執行時間的度量。

+0

如果我想對方法'm'的運行時間進行基準測試,將在有用的上下文中使用,那麼優化'm'就沒有意義了。我不是在討論任何(多餘的)對輔助方法的調用,而是「主要」方法。 – Raphael

+0

你想我的觀點。如果「主要」方法在實際程序中得到優化,那麼這是否意味着如果不在基準測試中對其進行優化就會導致錯誤結果?或者,也許你在自己​​的問題中沒有足夠清楚地解釋自己...... –

+0

它只是基準測試(例如,排序數組計算階乘的方法)的主要方法,而不是「真實」世界。 – Raphael

0

基準的目的是讓儘可能接近實際性能越好,所以我不知道你會得到這裏。如果您懷疑JIT會做某些事情,並且您不希望在正常使用中實際禁用它,那麼最好的辦法就是用這個假設來構建基準。如果有方法可以編寫基準來強調它,並使其在JIT下表現得效率低下,那麼這可能也很有用,因爲在分析器下運行基準將有助於找出其效率下降的時間。

相關問題