簡體   English   中英

為什么短原始類型明顯慢於long或int?

[英]Why is the short primitive type significantly slower than long or int?

我嘗試通過將int基元更改為short來優化Android游戲的RAM使用率。 在我這樣做之前,我對Java中原始類型的性能感興趣。

所以我使用caliper庫創建了這個小測試基准。

public class BenchmarkTypes extends Benchmark {

    @Param("10") private long testLong;
    @Param("10") private int testInt;
    @Param("10") private short testShort;


    @Param("5000") private long resultLong = 5000;
    @Param("5000") private int resultInt = 5000;
    @Param("5000") private short resultShort = 5000;

    @Override
    protected void setUp() throws Exception {
        Random rand = new Random();

        testShort = (short) rand.nextInt(1000);
        testInt = (int) testShort;
        testLong = (long) testShort;
    }

    public long timeLong(int reps){
        for(int i = 0; i < reps; i++){
            resultLong += testLong;
            resultLong -= testLong;         
        }
        return resultLong;
    }

    public int timeInt(int reps){
        for(int i = 0; i < reps; i++){
            resultInt += testInt;
            resultInt -= testInt;           
        }
        return resultInt;
    }

    public short timeShort(int reps){
        for(int i = 0; i < reps; i++){
            resultShort += testShort;
            resultShort -= testShort;
        }
        return resultShort;
    }
}

測試結果讓我感到驚訝。

測試環境

基准測試在Caliper庫下運行。

檢測結果

https://microbenchmarks.appspot.com/runs/0c9bd212-feeb-4f8f-896c-e027b85dfe3b

Int 2.365 ns

長2.436 ns

短8.156 ns

測試結論?

短基元類型比long和int基元類型慢得多(3-4~)?

  1. 為什么短原語明顯慢於int或long? 我希望int原語類型在32位虛擬機上最快,長短在時間上相等,或者短到甚至更快。

  2. Android手機也是如此嗎? 知道Android手機通常在32位環境中運行,現在越來越多的手機開始配備64位處理器。

Java字節代碼不支持小於int的基本類型的基本操作(+, - ,*,/,>>,>>>,<<,%)。 在指令集中沒有為這種操作分配字節代碼。 因此,VM需要將short(s)轉換為int(s),執行操作,然后將int截斷為short並將其存儲在結果中。

使用javap檢查生成的字節代碼,以查看short和int測試之間的區別。

VM / JIT優化顯然偏向於int / long操作,這是有意義的,因為它們是最常見的。

小於int的類型有其用途,但主要用於在數組中保存內存。 它們不像簡單的類成員那樣適合(當然,當它適用於數據的類型時,你仍然會使用它們)。 較小的成員甚至可能不會減小對象大小。 當前VM(再次)主要針對執行速度而定制,因此VM甚至可以將字段與本機機器字邊界對齊以提高訪問性能,但代價是內存花費。

由於java / android處理小於int的基元的整數算術的方式是可能的。

如果在java中添加了兩個原語,這些原語的數據類型小於int,則會自動將它們提升為整數數據類型。 通常需要強制轉換才能將結果轉換回必要的數據類型。

訣竅來自簡寫操作,如+=-=等,其中演員隱式發生,以便操作的最終結果:

resultShort += testShort;

實際上類似於這樣的事情:

resultShort = (short)((int) resultShort + (int) testShort);

如果我們查看方法的反匯編字節碼:

public static int test(int a, int b){
    a += b;
    return a;
}

我們看:

public static int test(int, int);
    Code:
       0: iload_0       
       1: iload_1       
       2: iadd          
       3: istore_0      
       4: iload_0       
       5: ireturn   

將此與數據類型的相同方法進行比較,我們得到:

public static short test(short, short);
    Code:
       0: iload_0       
       1: iload_1       
       2: iadd          
       3: i2s           
       4: istore_0      
       5: iload_0
       6: ireturn

注意附加指令i2s (整數到短)。 這可能是性能損失的罪魁禍首。 您可以注意到的另一件事是所有指令都是基於整數的,由前綴i表示(例如, iadd表示整數加)。 這意味着在iload階段的某個地方,短路被提升為整數,這可能也會導致性能下降。

如果你可以接受我的話,長算術的字節碼與整數的字節碼相同,但指令是長特定的(例如ladd而不是iadd )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM