簡體   English   中英

為什么訪問 volatile 變量比 member 慢 100 左右?

[英]Why access volatile variable is about 100 slower than member?

這里我寫了一個關於local、member、volatile成員訪問速度的測試:

public class VolatileTest {

public int member = -100;

public volatile int volatileMember = -100;

public static void main(String[] args) {
    int testloop = 10;
    for (int i = 1; i <= testloop; i++) {
        System.out.println("Round:" + i);
        VolatileTest vt = new VolatileTest();
        vt.runTest();
        System.out.println();
    }
}

public void runTest() {
    int local = -100;

    int loop = 1;
    int loop2 = Integer.MAX_VALUE;
    long startTime;

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
        }
        for (int j = 0; j < loop2; j++) {
        }
    }
    System.out.println("Empty:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            local++;
        }
        for (int j = 0; j < loop2; j++) {
            local--;
        }
    }
    System.out.println("Local:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            member++;
        }
        for (int j = 0; j < loop2; j++) {
            member--;
        }
    }
    System.out.println("Member:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            volatileMember++;
        }
        for (int j = 0; j < loop2; j++) {
            volatileMember--;
        }
    }
    System.out.println("VMember:" + (System.currentTimeMillis() - startTime));

}
}

這是我的 X220(I5 CPU)上的結果:

Round:1空車:5 Local:10 Member:312 VMember:33378

輪數:2空車數:31 本地數:0 會員數:294 V會員數:33180

輪次:3空車:0 本地:0 會員:306 VM會員:33085

回合數:4空數:0 本地數:0 會員數:300 虛擬會員數:33066

輪次:5空車:0 本地:0 會員:303 VM會員:33078

輪數:6空車數:0 本地數:0 會員數:299 虛擬會員數:33398

輪數:7空車數:0 本地數:0 會員數:305 虛擬會員數:33139

輪次:8空車:0 本地:0 會員:307 VM會員:33490

輪次:9空車:0 本地:0 會員:350 VM會員:35291

輪次:10空車:0 本地:0 會員:332 VM會員:33838

令我驚訝的是,訪問 volatile 成員比普通成員慢 100 倍。 我知道關於 volatile 成員有一些突出的特性,比如對它的修改將立即對所有線程可見,對 volatile 變量的訪問點起着“內存屏障”的作用。 但是所有這些副作用會是慢 100 倍的主要原因嗎?

PS:我也在Core II CPU機器上做過測試。 大約是9:50,慢了大約5倍。 似乎這也與 CPU 架構有關。 5倍還是很大吧?

volatile 成員從不被緩存,所以它們直接從主內存中讀取。

訪問volatile變量會阻止 CPU 在訪問前后對指令進行重新排序,這通常會減慢執行速度。

訪問volatile會阻止一些 JIT 優化。 如果您有一個實際上不執行任何操作的循環,這一點尤其重要,因為 JIT 可以優化此類循環(除非您有一個 volatile 字段)如果您“長時間”運行循環,差異應該會增加更多。

在更實際的測試中,您可能預計volatile對關鍵代碼的處理速度要慢 30% 到 10 倍。 在大多數實際程序中,它幾乎沒有什么區別,因為 CPU 足夠聰明,可以“意識到”只有一個內核在使用易失性字段並緩存它而不是使用主內存。

使用volatile會直接從內存中讀取,這樣cpu的每個核心都會在下一次get時從變量中獲取變化,沒有使用cpu緩存,不會使用寄存器,L1~L3緩存技術,讀取自

  1. 寄存器 1 個時鍾周期
  2. 一級緩存 4 個時鍾周期
  3. 二級緩存 11 個時鍾周期
  4. L3緩存30~40個時鍾周期
  5. 內存 100+ 時鍾周期

這就是為什么使用 volatile 時你的結果會慢大約 100 倍。

暫無
暫無

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

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