Differenze reali tra "java -server" e "java -client"?


394

C'è qualche reale differenza pratica tra "java -server" e "java -client"?

Tutto quello che posso trovare sul sito di Sun è vago

"-server si avvia più lentamente ma dovrebbe funzionare più veloce".

Quali sono le vere differenze? (Utilizzando attualmente JDK 1.6.0_07.)

Risposte:


368

Questo è veramente collegato a HotSpot e ai valori delle opzioni predefinite ( Opzioni VM HotSpot Java ) che differiscono tra la configurazione client e server.

Dal capitolo 2 del white paper ( Java HotSpot Performance Engine Architecture ):

JDK include due versioni della VM: un'offerta lato client e una VM ottimizzata per le applicazioni server. Queste due soluzioni condividono la base di codice dell'ambiente di runtime Java HotSpot, ma utilizzano compilatori diversi che si adattano alle caratteristiche di prestazioni distintamente uniche di client e server. Queste differenze includono la politica di compilazione in linea e le impostazioni predefinite dell'heap.

Sebbene le VM Server e Client siano simili, la VM Server è stata appositamente ottimizzata per massimizzare la massima velocità operativa. È destinato all'esecuzione di applicazioni server a esecuzione prolungata, che richiedono la massima velocità operativa maggiore rispetto a un tempo di avvio rapido o un footprint di memoria di runtime inferiore.

Il compilatore VM client funge da aggiornamento sia per i compilatori VM classici sia per i just-in-time (JIT) utilizzati dalle versioni precedenti di JDK. La VM client offre prestazioni di runtime migliorate per applicazioni e applet. La VM client HotSpot Java è stata appositamente ottimizzata per ridurre i tempi di avvio dell'applicazione e il footprint di memoria, rendendola particolarmente adatta agli ambienti client. In generale, il sistema client è migliore per le GUI.

Quindi la vera differenza è anche a livello di compilatore:

Il compilatore VM client non tenta di eseguire molte delle ottimizzazioni più complesse eseguite dal compilatore nella VM server, ma in cambio richiede meno tempo per analizzare e compilare un pezzo di codice. Ciò significa che la VM client può avviarsi più velocemente e richiede un ingombro di memoria inferiore.

La VM del server contiene un compilatore adattivo avanzato che supporta molti degli stessi tipi di ottimizzazioni eseguite ottimizzando i compilatori C ++, nonché alcune ottimizzazioni che non possono essere eseguite dai compilatori tradizionali, come l'inserimento aggressivo nelle invocazioni di metodi virtuali. Questo è un vantaggio competitivo e prestazionale rispetto ai compilatori statici. La tecnologia di ottimizzazione adattiva è molto flessibile nel suo approccio e in genere supera anche le tecniche avanzate di analisi statica e compilazione.

Nota: il rilascio dell'aggiornamento 10 jdk6 (consultare Note di rilascio dell'aggiornamento: modifiche in 1.6.0_10 ) ha cercato di migliorare i tempi di avvio, ma per un motivo diverso rispetto alle opzioni dell'hotspot, essendo impacchettato in modo diverso con un kernel molto più piccolo.


G. Demecki sottolinea nei commenti che nelle versioni a 64 bit di JDK, l' -clientopzione viene ignorata per molti anni.
Vedi il comando di Windowsjava :

-client

Seleziona la VM client HotSpot Java.
Un JDK a 64 bit attualmente ignora questa opzione e utilizza invece la VM Java Hotspot Server .


7
jdk6 aggiornamento 10 e successivi hanno un processo in background che mantiene in memoria le librerie di runtime consentendo un avvio molto più veloce per i nuovi processi rispetto alla necessità di pagarlo tutto su richiesta.
Thorbjørn Ravn Andersen,

1
Pensavo che anche il cliente fosse in modo aggressivo, vabbè.
Thorbjørn Ravn Andersen,

1
Penso che questa risposta debba essere aggiornata. Perché nelle versioni a 64 bit di JDK l' -clientopzione viene ignorata per molti anni.
G. Demecki,

@ G.Demecki Certo: hai un link che documenta che questa opzione è obsoleta o ignorata?
VonC

1
Sicuro. Ecco alcuni documenti per Java 7 per Windows. E sorprendentemente un'informazione simile può essere trovata anche nella documentazione di Java 6 .
G. Demecki,

90

La differenza immediata più visibile nelle versioni precedenti di Java sarebbe la memoria allocata a una -clientinvece di -serverun'applicazione. Ad esempio, sul mio sistema Linux, ottengo:

$ 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"

come impostazione predefinita -server, ma con l' -clientopzione ottengo:

$ 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"

quindi con la -servermaggior parte dei limiti di memoria e le allocazioni iniziali sono molto più alte per questa javaversione.

Questi valori possono tuttavia cambiare per diverse combinazioni di architettura, sistema operativo e versione jvm. Le versioni recenti di jvm hanno rimosso i flag e spostato molte delle distinzioni tra server e client.

Ricorda anche che puoi vedere tutti i dettagli di una corsa jvmusando jvisualvm. Ciò è utile se si dispone di utenti o moduli che impostano JAVA_OPTSo utilizzano script che modificano le opzioni della riga di comando. Questo ti permetterà anche di monitorare, in tempo reale, l' utilizzo dello spazio heap e permgen insieme a molte altre statistiche.


2
Mi dà gli stessi numeri sulle modalità -server e -client per la versione java "1.7.0_79" su CentOS 7 [Java (TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot (TM) VM 64-Bit Server ]
Basil Musa

4
Questo è il motivo per cui ho fornito la risposta. Non si tratta dei valori, si tratta di consentire a chiunque, in qualsiasi momento, di trovare la risposta per la propria versione jvm specifica.
Mark Booth,

33

i sistemi -client e -server sono binari diversi. Sono essenzialmente due diversi compilatori (JIT) che si interfacciano allo stesso sistema di runtime. Il sistema client è ottimale per applicazioni che richiedono tempi di avvio rapidi o ingombri ridotti, il sistema server è ottimale per applicazioni in cui le prestazioni complessive sono più importanti. In generale, il sistema client è più adatto per applicazioni interattive come le GUI

inserisci qui la descrizione dell'immagine

Eseguiamo il seguente codice con entrambi gli switch:

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--) {
        }
    }
}

Nota: il codice è stato compilato una sola volta! Le classi sono le stesse in entrambe le sessioni!

Con -client:
java.exe -client -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Tempo impiegato: 766

Con -server:
java.exe -server -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Tempo impiegato: 0

Sembra che l'ottimizzazione più aggressiva del sistema server, rimuova il ciclo in quanto comprende che non esegue alcuna azione!

Riferimento


33

Una differenza che ho appena notato è che in modalità "client", sembra che la JVM restituisca effettivamente una memoria non utilizzata al sistema operativo, mentre con la modalità "server", una volta che la JVM cattura la memoria, non la darà indietro. Ecco come appare su Solaris con Java6 comunque (usando prstat -Zper vedere la quantità di memoria allocata a un processo).


22

La documentazione online di Oracle fornisce alcune informazioni per Java SE 7.

Sul java - la pagina di avvio dell'applicazione Java per Windows, l' -clientopzione viene ignorata in un JDK a 64 bit:

Selezionare la VM client HotSpot Java. Un jdk a 64 bit attualmente ignora questa opzione e utilizza invece la VM Java HotSpot Server.

Tuttavia (per rendere le cose interessanti), sotto -serverafferma:

Seleziona la VM Java HotSpot Server. Su un jdk a 64 bit è supportata solo la VM Java HotSpot Server, quindi l'opzione -server è implicita. Questo è soggetto a modifiche in una versione futura.

La pagina Rilevamento macchina di classe server fornisce informazioni su quale VM è selezionata per sistema operativo e architettura.

Non so quanto di ciò si applichi a JDK 6.


2
Grazie, mi chiedevo come mai non ho visto un client / jvm.dll su JDK7
Archimedes Trajano

16

Da Goetz - Java Concurrency in Practice:

  1. Suggerimento per il debug: per le applicazioni server, assicurarsi di specificare sempre l' -serveropzione della riga di comando JVM quando si richiama JVM, anche per lo sviluppo e il test . Il server JVM esegue una maggiore ottimizzazione rispetto al client JVM, ad esempio sollevando le variabili da un ciclo che non sono modificate nel ciclo; il codice che potrebbe sembrare funzionare nell'ambiente di sviluppo (client JVM) può rompersi nell'ambiente di distribuzione (server JVM). Ad esempio, se avessimo “dimenticato” di dichiarare volatile la variabile nel Listato 3.4, il server JVM potrebbe sollevare il test dal loop (trasformandolo in un loop infinito), ma il client JVM no . Un ciclo infinito che si presenta in sviluppo è molto meno costoso di uno che si presenta solo in produzione.

Elenco 3.4. Contare le pecore.

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

La mia enfasi. YMMV


15

IIRC la VM del server esegue più ottimizzazioni di hotspot all'avvio, quindi funziona più velocemente ma richiede un po 'più tempo per avviarsi e utilizza più memoria. La VM client difende gran parte dell'ottimizzazione per consentire un avvio più rapido.

Modifica per aggiungere: ecco alcune informazioni di Sun, non sono molto specifiche ma ti daranno alcune idee.


5

IIRC, prevede strategie di raccolta dei rifiuti. La teoria è che un client e un server saranno diversi in termini di oggetti di breve durata, il che è importante per i moderni algoritmi GC.

Ecco un link in modalità server. Purtroppo, non menzionano la modalità client.

Ecco un link molto completo su GC in generale; questo è un articolo più fondamentale . Non sono sicuro se l'indirizzo-server vs -client ma questo è materiale pertinente.

In No Fluff Just Stuff, sia Ken Sipe che Glenn Vandenburg parlano alla grande di questo genere di cose.


3

Non ho notato alcuna differenza nei tempi di avvio tra i 2, ma ho registrato un miglioramento minimo delle prestazioni dell'applicazione con "-server" (server Solaris, tutti usano SunRays per eseguire l'app). Quello era meno di 1.5.


6
Dipende da cosa sta facendo il tuo programma. Per alcune applicazioni ad uso intensivo di processore che ripetutamente fanno la stessa cosa, ho notato enormi miglioramenti (fino a 10x) con -server.
Dan Dyer,

1
Dan, hai un riferimento a questo? Vorrei indagare ulteriormente.
Thorbjørn Ravn Andersen,

1
L'esecuzione di Sunflow con la VM del server è MOLTO più veloce del client. sunflow.sourceforge.net
John,

1

L'ultima volta che ho dato un'occhiata a questo, (e certamente è stato un po 'di tempo fa) la più grande differenza che ho notato era nella raccolta dei rifiuti.

IIRC:

  • La VM heap del server ha un numero di generazioni diverso rispetto alla VM client e un algoritmo di garbage collection diverso. Questo potrebbe non essere più vero
  • La VM del server alloca la memoria e non la rilascia sul sistema operativo
  • La VM del server utilizzerà algoritmi di ottimizzazione più sofisticati e quindi avrà requisiti di tempo e memoria maggiori per l'ottimizzazione

Se puoi confrontare due VM Java, un client e un server utilizzando lo strumento jvisualvm , dovresti vedere una differenza nella frequenza e nell'effetto della garbage collection, nonché nel numero di generazioni.

Ho avuto un paio di schermate che mostravano la differenza davvero bene, ma non riesco a riprodurre poiché ho una JVM a 64 bit che implementa solo la VM del server. (E non posso essere disturbato a scaricare e adattare anche la versione a 32 bit sul mio sistema.)

Questo non sembra più essere il caso, dopo aver provato a eseguire un po 'di codice su Windows con VM sia server che client, mi sembra di ottenere lo stesso modello di generazione per entrambi ...


1

Quando si esegue una migrazione dalla versione 1.4 alla 1.7 ("1.7.0_55"). La cosa che abbiamo osservato qui è che non ci sono tali differenze nei valori predefiniti assegnati ai parametri heapsize | permsize | ThreadStackSize in modalità client e server.

A proposito, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Questo è lo snippet preso dal link sopra.

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

ThreadStackSize è più alto in 1.7, mentre passa attraverso il forum Open JDK, ci sono discussioni che affermano che la dimensione del frame è leggermente più alta nella versione 1.7. Si ritiene che la reale differenza possa essere misurata in fase di esecuzione in base al comportamento dell'applicazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.