Rzeczywiste różnice między „java -server” a „java -client”?

394

Czy istnieje jakaś praktyczna różnica między „java -server” a „java -client”?

Wszystko, co mogę znaleźć na stronie Sun, jest niejasne

„-server uruchamia się wolniej, ale powinien działać szybciej”.

Jakie są prawdziwe różnice? (Obecnie używa JDK 1.6.0_07.)

Paul Tomblin
źródło

Odpowiedzi:

368

Jest to naprawdę powiązane z HotSpot i domyślnymi wartościami opcji ( Opcje VM HotSpot VM ), które różnią się w zależności od konfiguracji klienta i serwera.

Z rozdziału 2 oficjalnego dokumentu ( Architektura silnika Java HotSpot Performance Engine ):

JDK obejmuje dwa warianty maszyny wirtualnej - ofertę dla klienta i maszynę wirtualną dostosowaną do aplikacji serwerowych. Te dwa rozwiązania współużytkują bazę kodu środowiska wykonawczego Java HotSpot, ale używają różnych kompilatorów, które są dostosowane do wyraźnie unikalnej charakterystyki wydajności klientów i serwerów. Różnice te obejmują zasady wstawiania kompilacji i wartości domyślne sterty.

Chociaż maszyny wirtualne serwera i klienta są podobne, maszyna wirtualna serwera została specjalnie dostrojona, aby zmaksymalizować maksymalną prędkość roboczą. Jest przeznaczony do uruchamiania długo działających aplikacji serwerowych, które wymagają najszybszej możliwej prędkości działania większej niż szybki czas uruchamiania lub mniejszy ślad pamięci wykonawczej.

Kompilator maszyn wirtualnych klienta służy jako uaktualnienie zarówno klasycznej maszyny wirtualnej, jak i kompilatorów just-in-time (JIT) używanych we wcześniejszych wersjach JDK. Klient maszyn wirtualnych oferuje lepszą wydajność w czasie wykonywania aplikacji i apletów. Wirtualna klient Java HotSpot została specjalnie dostrojona, aby skrócić czas uruchamiania aplikacji i zajmować mało pamięci, dzięki czemu jest szczególnie odpowiedni dla środowisk klienckich. Ogólnie rzecz biorąc, system klienta jest lepszy dla GUI.

Tak więc prawdziwa różnica występuje również na poziomie kompilatora:

Kompilator VM maszyny klienckiej nie próbuje wykonać wielu bardziej złożonych optymalizacji przeprowadzanych przez kompilator w maszynie VM serwera, ale w zamian zajmuje mniej czasu na analizę i kompilację fragmentu kodu. Oznacza to, że maszyna wirtualna klienta może uruchamiać się szybciej i wymaga mniejszej pojemności pamięci.

Serwerowa maszyna wirtualna zawiera zaawansowany adaptacyjny kompilator, który obsługuje wiele takich samych rodzajów optymalizacji przeprowadzanych przez optymalizację kompilatorów C ++, a także niektóre optymalizacje, których nie można wykonać za pomocą tradycyjnych kompilatorów, takie jak agresywne wprowadzanie w wirtualne wywołania metod. Jest to przewaga konkurencyjna i wydajnościowa w stosunku do kompilatorów statycznych. Technologia optymalizacji adaptacyjnej jest bardzo elastyczna i zazwyczaj przewyższa nawet zaawansowane techniki analizy statycznej i kompilacji.

Uwaga: Wydanie aktualizacji 10 jdk6 (patrz Uwagi do wydania aktualizacji: Zmiany w wersji 1.6.0_10 ) próbowało skrócić czas uruchamiania, ale z innego powodu niż opcje hotspotu, ponieważ jest pakowane inaczej z dużo mniejszym jądrem.


G. Demecki wskazuje w komentarzach, że w 64-bitowych wersjach JDK -clientopcja ta jest ignorowana przez wiele lat.
Zobacz polecenie systemu Windowsjava :

-client

Wybiera maszynę wirtualną klienta Java HotSpot.
JDK obsługujący 64-bit obecnie ignoruje tę opcję i zamiast tego używa maszyny wirtualnej Java Hotspot Server .

VonC
źródło
7
Jdk6, aktualizacja 10 i nowsze, mają proces działający w tle, który utrzymuje biblioteki wykonawcze w pamięci, co pozwala na znacznie szybsze uruchamianie nowych procesów niż konieczność stronicowania ich na żądanie.
Thorbjørn Ravn Andersen
1
Myślałem, że vm klienta również agresywnie, no cóż.
Thorbjørn Ravn Andersen
1
Myślę, że ta odpowiedź powinna zostać zaktualizowana. Ponieważ w 64-bitowych wersjach JDK -clientopcja jest ignorowana przez wiele lat.
G. Demecki,
@ G.Demecki Pewnie: czy masz link dokumentujący, że ta opcja jest przestarzała lub zignorowana?
VCC
1
Pewnie. Oto dokumentacja dla Java 7 dla Windows. I, co zaskakujące, podobne informacje można znaleźć również w dokumentacji Java 6 .
G. Demecki
90

Najbardziej widoczną bezpośrednią różnicą w starszych wersjach Javy byłaby pamięć przydzielona do aplikacji, -clienta nie do -serveraplikacji. Na przykład w moim systemie Linux otrzymuję:

$ java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight               = 20               {product}
uintx ErgoHeapSizeLimit                    = 0                {product}
uintx InitialHeapSize                     := 66328448         {product}
uintx LargePageHeapSizeThreshold           = 134217728        {product}
uintx MaxHeapSize                         := 1063256064       {product}
uintx MaxPermSize                          = 67108864         {pd product}
uintx PermSize                             = 16777216         {pd product}
java version "1.6.0_24"

jak domyślnie -server, ale z -clientopcją dostaję:

$ java -client -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight               = 20               {product}
uintx ErgoHeapSizeLimit                    = 0                {product}
uintx InitialHeapSize                     := 16777216         {product}
uintx LargePageHeapSizeThreshold           = 134217728        {product}
uintx MaxHeapSize                         := 268435456        {product}
uintx MaxPermSize                          = 67108864         {pd product}
uintx PermSize                             = 12582912         {pd product}
java version "1.6.0_24"

więc przy -serverwiększości limitów pamięci i początkowych przydziałach są znacznie wyższe dla tej javawersji.

Wartości te mogą się jednak zmieniać dla różnych kombinacji architektury, systemu operacyjnego i wersji jvm. Najnowsze wersje Jvm usunęły flagi i usunęły wiele różnic między serwerem a klientem.

Pamiętaj też, że można zobaczyć wszystkie szczegóły uruchomiony jvmużyciu jvisualvm. Jest to przydatne, jeśli masz użytkowników, którzy lub moduły, które ustawiają JAVA_OPTSlub używają skryptów zmieniających opcje wiersza poleceń. Umożliwi to również monitorowanie w czasie rzeczywistym zużycia miejsca na sterty i permgenach oraz wielu innych statystyk.

Mark Booth
źródło
2
Daje mi te same numery w trybach serwera i klienta dla wersji java „1.7.0_79” na CentOS 7 [Java (TM) SE Runtime Environment (kompilacja 1.7.0_79-b15) Java HotSpot (TM) 64-bitowa maszyna wirtualna serwera ]
Basil Musa
4
Dlatego udzieliłem odpowiedzi. Nie chodzi o wartości, chodzi o umożliwienie każdemu, w dowolnym momencie, znalezienia odpowiedzi dla konkretnej wersji JVM.
Mark Booth
33

systemy -client i -server są różnymi plikami binarnymi. Są to zasadniczo dwa różne kompilatory (JIT) współpracujące z tym samym systemem wykonawczym. System kliencki jest optymalny dla aplikacji, które wymagają krótkich czasów uruchamiania lub małych wymagań, system serwerowy jest optymalny dla aplikacji, w których ogólna wydajność jest najważniejsza. Zasadniczo system klienta lepiej nadaje się do interaktywnych aplikacji, takich jak GUI

wprowadź opis zdjęcia tutaj

Uruchamiamy następujący kod z obydwoma przełącznikami:

package com.blogspot.sdoulger;

public class LoopTest {
    public LoopTest() {
        super();
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        spendTime();
        long end = System.currentTimeMillis();
        System.out.println("Time spent: "+ (end-start));

        LoopTest loopTest = new LoopTest();
    }

    private static void spendTime() {
        for (int i =500000000;i>0;i--) {
        }
    }
}

Uwaga: Kod został skompilowany tylko raz! Klasy są takie same w obu seriach!

Z opcją -client:
java.exe -client -classpath C: \ mywork \ klas com.blogspot.sdoulger.LoopTest
Czas spędzony: 766

Z -server:
java.exe -server -classpath C: \ mywork \ klas com.blogspot.sdoulger.LoopTest
Czas spędzony: 0

Wydaje się, że im bardziej agresywna optymalizacja systemu serwera, usuń pętlę, ponieważ rozumie ona, że ​​nie wykonuje żadnej akcji!

Odniesienie

Premraj
źródło
33

Jedną z różnic, które właśnie zauważyłem, jest to, że w trybie „klienta” wydaje się, że JVM faktycznie oddaje część nieużywanej pamięci z powrotem do systemu operacyjnego, natomiast w trybie „serwera”, gdy JVM pobierze pamięć, nie da jej plecy. Tak to wygląda w Solarisie z Javą 6 (przy użyciu, prstat -Zaby zobaczyć ilość pamięci przydzielonej procesowi).

prule
źródło
22

Dokumentacja online Oracle zawiera pewne informacje dotyczące Java SE 7.

Na java - stronie uruchamiania aplikacji Java dla Windows, -clientopcja jest ignorowana w 64-bitowym JDK:

Wybierz maszynę wirtualną Java HotSpot Client. Jdk obsługujący 64-bit obecnie ignoruje tę opcję i zamiast tego korzysta z maszyny wirtualnej Java HotSpot Server.

Jednak (aby uczynić rzeczy interesującymi), pod -servernim stwierdza:

Wybierz maszynę wirtualną Java HotSpot Server. W 64-bitowym jdk obsługiwana jest tylko maszyna wirtualna Java HotSpot Server, więc domyślna jest opcja -server. To może ulec zmianie w przyszłej wersji.

Wykrywanie Server Class Maszyna strona zawiera informacje na VM, który jest wybrany przez OS i architekturze.

Nie wiem, ile z tego dotyczy JDK 6.

siklawa
źródło
2
Dzięki, zastanawiałem się, dlaczego nie widziałem klienta / jvm.dll na JDK7
Archimedes Trajano
16

From Goetz - Java Concurrency in Practice:

  1. Wskazówka dotycząca debugowania: w przypadku aplikacji serwerowych należy zawsze określać -serverprzełącznik wiersza polecenia JVM podczas wywoływania JVM, nawet w celu programowania i testowania . Serwer JVM wykonuje większą optymalizację niż JVM klienta, na przykład wyciągając zmienne z pętli, które nie są modyfikowane w pętli; kod, który może wydawać się działać w środowisku programistycznym (JVM klienta), może ulec awarii w środowisku wdrażania (JVM serwera). Na przykład, gdybyśmy „zapomnieli” zadeklarować zmienną śpiącą jako zmienną na Listingu 3.4, serwer JVM mógłby wyciągnąć test z pętli (zamieniając go w pętlę nieskończoną), ale JVM klienta nie zrobiłby tego . Nieskończona pętla, która pojawia się w fazie rozwoju, jest znacznie tańsza niż pętla, która pojawia się tylko w produkcji.

Listing 3.4. Liczenie owiec.

volatile boolean asleep; ... while (!asleep) countSomeSheep();

Mój nacisk. YMMV

Adam
źródło
15

IIRC maszyna wirtualna serwera wykonuje więcej optymalizacji hotspotów podczas uruchamiania, więc działa szybciej, ale jej uruchomienie zajmuje trochę więcej czasu i zużywa więcej pamięci. VM klienta odkłada większość optymalizacji, aby umożliwić szybsze uruchomienie.

Edytuj, aby dodać: oto kilka informacji od firmy Sun. Nie jest to zbyt szczegółowe, ale da ci kilka pomysłów.

Mike Akers
źródło
5

IIRC, obejmuje strategie usuwania śmieci. Teoria jest taka, że ​​klient i serwer będą się różniły pod względem obiektów krótkotrwałych, co jest ważne w nowoczesnych algorytmach GC.

Oto link w trybie serwera. Niestety, nie wspominają o trybie klienta.

Oto ogólnie bardzo dokładny link do GC; to jest bardziej podstawowy artykuł . Nie jestem pewien, czy któryś adres-serwer kontra klient, ale jest to istotny materiał.

W No Fluff Just Stuff zarówno Ken Sipe, jak i Glenn Vandenburg prowadzą świetne rozmowy na ten temat.

Michael Easter
źródło
3

Nie zauważyłem żadnej różnicy w czasie uruchamiania między tymi dwoma, ale taktowałem bardzo minimalną poprawę wydajności aplikacji za pomocą „-server” (serwer Solaris, wszyscy używający SunRays do uruchomienia aplikacji). To było poniżej 1,5.

Brian Knoblauch
źródło
6
Zależy od tego, co robi twój program. W przypadku niektórych aplikacji intensywnie wykorzystujących procesor, które powtarzają tę samą czynność, zauważyłem ogromne (nawet 10-krotnie) ulepszenia w opcji -server.
Dan Dyer
1
Dan, czy masz na to odniesienie? Chciałbym zbadać dalej.
Thorbjørn Ravn Andersen
1
Uruchamianie Sunflow z maszyną wirtualną serwera jest DUŻO szybsze niż klient. sunflow.sourceforge.net
John
1

Ostatnim razem, gdy na to spojrzałem (i muszę przyznać, że było to dawno temu), największą różnicą, jaką zauważyłem, była kolekcja śmieci.

IIRC:

  • Maszyna wirtualna sterty serwerów ma inną liczbę generacji niż maszyna wirtualna klienta i inny algorytm wyrzucania elementów bezużytecznych. To może już nie być prawda
  • Serwerowa maszyna wirtualna przydzieli pamięć i nie zwolni jej do systemu operacyjnego
  • Serwerowa maszyna wirtualna użyje bardziej wyrafinowanych algorytmów optymalizacyjnych, a zatem będzie miała większe wymagania dotyczące czasu i pamięci do optymalizacji

Jeśli możesz porównać dwie maszyny wirtualne Java, jeden klient, jeden serwer za pomocą narzędzia jvisualvm , powinieneś zobaczyć różnicę w częstotliwości i efekcie wyrzucania elementów bezużytecznych, a także w liczbie pokoleń.

Miałem parę zrzutów ekranu, które pokazały różnicę naprawdę dobrze, ale nie mogę się odtworzyć, ponieważ mam 64-bitową maszynę JVM, która implementuje tylko maszynę wirtualną serwera. (Nie mogę się też martwić pobraniem i sprowadzeniem wersji 32-bitowej na mój system.)

Wydaje się, że już tak nie jest, po próbie uruchomienia kodu w systemie Windows na maszynach wirtualnych serwera i klienta, wydaje mi się, że mam ten sam model generacji dla obu ...

brice
źródło
1

Podczas migracji z wersji 1.4 do 1.7 („1.7.0_55”), zaobserwowaliśmy tutaj, że nie ma takich różnic w wartościach domyślnych przypisanych do parametrów heapsize | permsize | ThreadStackSize w trybie klienta i serwera.

Nawiasem mówiąc, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). To jest fragment kodu pobrany z powyższego linku.

initial heap size of 1/64 of physical memory up to 1Gbyte
maximum heap size of ¼ of physical memory up to 1Gbyte

ThreadStackSize jest wyższy w wersji 1.7, podczas gdy przechodzimy przez forum Open JDK, istnieją dyskusje, które stwierdzają, że rozmiar ramki jest nieco wyższy w wersji 1.7. Uważa się, że rzeczywista różnica może być możliwa do zmierzenia w czasie wykonywania na podstawie zachowania aplikacji

Nuwan Arambage
źródło