2012-09-01 22 views
8

我正在將某種數據處理算法從Java移植到C++。重寫代碼的原因是可移植性,它需要在Java不可用的環境中運行。然而,作爲一個副作用,預計會有一些性能改進。Java中.getClass()的價格是多少?

基本上,該算法從由指向對方的對象組成的圖形中讀取數據,然後計算結果。在計算過程中會進行許多對象分配,所以也許這是造成放緩的原因。事情是,C++代碼目前的運行速度比舊Java代碼快10倍。這真是出乎意料。我只以爲我會看到50-60%的改善。

不幸的是,我不能隨意在這裏發佈代碼進行分析。這是幾千行,所以我不知道這將是多麼方便。

問題是,算法幾乎完全一樣。我能想到的唯一的主要區別是在Java中有許多女兒類的單個超類,如果(object.getClass()== daughterx.class)在計算過程中被多次調用,而在C++代碼中只有一個通用類被使用(因爲子類之間的代碼差異很少),並且使用簡單的整數比較。 if(object-> type == 15)

Java中的Object.getClass()方法有多昂貴?在調用此方法時,底層究竟發生了什麼?

+5

的因素@ xlc0212提高也不是任何其他人不理解Java的! ;) – cheeken

+0

@cheeken它取決於JVM,沒有JIT,我記得我從某處讀過Java比python慢​​甚至更慢 –

+3

老實說這聽起來像是一個沒有問題的東西。是否值得您花時間對已棄用的代碼進行基準測試和分析?除非你這樣做,否則無法知道'.getClass()'是瓶頸。除非可以顯着降低算法的總體複雜度(即從N平方運算變爲log-N運算),並且數據集非常大,否則猜測不是有效的調試性能問題的方法。 –

回答

7

10倍差異最有可能的情況是JVM沒有完全預熱。如果你不這樣做,即使在Java中,你也可以看到超過10倍的性能差異。我會嘗試以10,000的批次運行,並忽略前幾次運行。

public static void main(String... args) throws IOException { 
    timeObjectGraph("First run", 1); 
    timeObjectGraph("Second run", 2); 
    timeObjectGraph("Next thousand", 1000); 
    for (int i = 0; i < 5; i++) 
     timeObjectGraph("Next ten thousand", 10000); 
} 

static int dontOptimiseAway = 0; 

public static void timeObjectGraph(String desc, int runs) throws IOException { 
    long start = System.nanoTime(); 
    for (int i = 0; i < runs; i++) { 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(out); 
     oos.writeObject(Calendar.getInstance()); 
     oos.close(); 
     dontOptimiseAway = out.toByteArray().length; 
    } 
    long time = System.nanoTime() - start; 
    System.out.printf("%s took an avg time of %,d ns%n", desc, time/runs); 
} 

打印

First run took an avg time of 37,509,488 ns 
Second run took an avg time of 439,054 ns 
Next thousand took an avg time of 185,242 ns 
Next ten thousand took an avg time of 41,698 ns 
Next ten thousand took an avg time of 19,981 ns 
Next ten thousand took an avg time of 11,541 ns 
Next ten thousand took an avg time of 13,451 ns 
Next ten thousand took an avg time of 11,289 ns 

從第一個到最後運行,其性能已通過的3000倍

+0

爲什麼你使用Calendar.getInstance()?首先問題是關於getClass方法。第二個日曆是**重**類創建的,所以Calendar.getInstance()**本身很昂貴**,而不是因爲getClass在裏面被調用。我認爲這個例子不正確,或者你應該提供更明確的評論。 – Cherry

+2

@Cherry我使用了Calendar和ObjectOutputStream,因爲這些代碼對於一小段代碼來說都很昂貴,這給出了一個現實的例子,即預熱可以爲大量代碼帶來多大的差異。 –

5

這不可能是性能差異的唯一因素。不幸的是,如果沒有你的代碼實際上做的更完整的圖片,很難告訴你發生了什麼事情。

根據我的經驗,沒有理由Java應該比C++慢10倍。我可能會從一個分析器開始,看看它指向哪個位置來理解問題,而不是猜測。

11

Java中的Object.getClass()方法有多昂貴?

根據我的它是如何在非主流的JVM實現的知識,它是便宜

恰好在低級別正在發生什麼調用此方法時?

通常...

  1. 提取從對象的標題的類索引(2組或3的指令)
  2. 查找從類索引的類描述符(2組或3的指令)
  3. 從類描述符中取回並返回Class對象引用(2或3條指令)

問題是,C++代碼的運行速度比舊Java代碼快10倍。

我期望性能瓶頸是在別的地方。您應該嘗試對Java代碼進行分析,然後才能得出有關爲何速度較慢的結論。

+6

+1雖然查找本身很便宜,但如果您有if(getClass()== SomeClass.class)序列,則這意味着顯着的設計和性能問題。「這表明您需要更多的OO Design或OP,組合這些類,以便它可以使用開關或類似的功能。 –

相關問題