2012-06-21 14 views
5

Tutaj pisałem test o szybkości dostępu lokalnego, członek, lotny członkiem:Dlaczego dostęp do zmiennej lotnej jest około 100 wolniejszy od członka?

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)); 

} 
} 

A oto wynik na moim X220 (I5 CPU):

Runda: 1 Empty: 5 lokalny: 10 użytkownika: 312 VMember: 33378

Runda: 2 Empty: 31 lokalny: 0 użytkownika: 294 VMember: 33180

Runda: 3 Empty: 0 lokalny: 0 użytkownika: 306 VMember: 33085

Runda: 4 Empty: 0 lokalny: 0 użytkownika: 300 VMember: 33066

runda: 5 Empty: 0 lokalny: 0 użytkownika: 303 VMember: 33078

Runda: 6 Empty: 0 lokalny: 0 użytkownika: 299 VMember: 33398

Runda: 7 Empty: 0 lokalny: 0 użytkownika: 305 VMember: 33139

Runda: 8 Empty: 0 lokalny: 0 użytkownika: 307 VMember: 33490

Runda: 9 Empty: 0 lokalny: 0 użytkownika: 350 VMember: 35291

Runda: 10 Empty: 0 lokalny: 0 użytkownika: 332 VMember: 33838

Zaskoczyło mnie, że dostęp do zmiennych członka jest 100 razy wolniej niż normalnie członka . Wiem, że istnieje pewna cecha wyróżniająca element niestabilny, na przykład modyfikacja będzie natychmiast widoczna dla wszystkich wątków, punkt dostępu do zmiennej lotnej pełni rolę "bariery pamięci". Ale czy wszystkie te skutki uboczne mogą być główną przyczyną 100-krotnego spowolnienia?

PS: Przeprowadziłem również test na komputerze z procesorem Core II. Jest około 9:50, około 5 razy wolniej. wydaje się, że jest to również związane z łukiem procesora. 5 razy jest nadal duże, prawda?

+0

możliwy duplikat [Czy lotny jest drogi?] (Http://stackoverflow.com/questions/4633866/is-volatile-efensive) –

+0

patrząc na to ... – DeepNightTwo

Odpowiedz

3

Dostęp do volatile zapobiega niektórym optymalizacjom JIT.Jest to szczególnie ważne, jeśli masz pętlę, która tak naprawdę nic nie robi, ponieważ JIT może zoptymalizować takie pętle (chyba że masz zmienne pole). Jeśli uruchomisz pętle "długo", odstępstwo powinno wzrosnąć bardziej.

W bardziej realistycznym teście można się spodziewać, że w przypadku kodu certykowego można uzyskać od 30% do 10 razy więcej wolniejszego. W większości rzeczywistych programów nie ma dużej różnicy, ponieważ procesor jest wystarczająco inteligentny, aby "zdać sobie sprawę", że tylko jeden rdzeń wykorzystuje zmienne pole i buforuje je zamiast używać pamięci głównej.

3

Dostęp do zmiennej volatile uniemożliwia procesorowi ponowne zamówienie instrukcji przed i po dostępie, co zazwyczaj spowalnia wykonywanie.

6

Zmienne elementy nie są nigdy buforowane, więc są odczytywane bezpośrednio z pamięci głównej.

+0

dokładnie. Dlaczego nie była to zaakceptowana odpowiedź. –

Powiązane problemy