Existe-t-il une réelle différence pratique entre "serveur Java" et "client Java"?
Tout ce que je peux trouver sur le site de Sun est vague
"-server démarre plus lentement mais devrait courir plus vite".
Quelles sont les vraies différences? (Utilisation de JDK 1.6.0_07 actuellement.)
Ceci est vraiment lié à HotSpot et aux valeurs par défaut ( Java HotSpot VM Options ) qui diffèrent entre la configuration du client et celle du serveur.
Extrait du Chapitre 2 du livre blanc ( L'architecture Java HotSpot Performance Engine ):
Le JDK comprend deux types de produits VM - une offre côté client et un VM optimisé pour les applications serveur. Ces deux solutions partagent la base de code d'environnement d'exécution HotSpot Java, mais utilisent des compilateurs différents, adaptés aux caractéristiques de performances distinctement uniques des clients et des serveurs. Ces différences incluent la stratégie en ligne de compilation et les valeurs par défaut du tas.
Bien que le serveur et les ordinateurs virtuels clients soient similaires, le serveur VM a été spécialement conçu pour optimiser la vitesse de fonctionnement maximale. Il est conçu pour exécuter des applications serveur de longue durée, qui nécessitent une vitesse de fonctionnement la plus rapide possible, supérieure à un temps de démarrage rapide ou à une taille réduite de la mémoire d'exécution.
Le compilateur Client VM sert de mise à niveau pour les compilateurs Classic VM et Just-in-Time (JIT) utilisés par les versions précédentes du JDK. Le client VM offre de meilleures performances d'exécution pour les applications et les applets. Le Java HotSpot Client VM a été spécialement conçu pour réduire le temps de démarrage des applications et l'encombrement de la mémoire, ce qui le rend particulièrement bien adapté aux environnements clients. En général, le système client est meilleur pour les interfaces graphiques.
La vraie différence se situe donc également au niveau du compilateur:
Le compilateur Client VM n'essaie pas d'exécuter la plupart des optimisations plus complexes effectuées par le compilateur dans la machine virtuelle serveur, mais en contrepartie, il nécessite moins de temps pour analyser et compiler un morceau de code. Cela signifie que le client VM peut démarrer plus rapidement et nécessite une empreinte mémoire réduite.
Le serveur VM contient un compilateur adaptatif avancé prenant en charge bon nombre des mêmes types d'optimisations effectuées par l'optimisation des compilateurs C++, ainsi que des optimisations qui ne peuvent pas être réalisées par les compilateurs traditionnels, telles que l'inlignage agressif des invocations de méthodes virtuelles. . C'est un avantage concurrentiel et de performance par rapport aux compilateurs statiques. La technologie d'optimisation adaptative est très flexible dans son approche et surpasse généralement même les techniques avancées d'analyse et de compilation statiques.
Remarque: La version de jdk6 mise à jour 10 (voir Notes de version de la mise à jour: Modifications dans 1.6.0_1 ) a tenté d'améliorer le temps de démarrage, mais pour une raison différente. que les options hotspot, étant empaqueté différemment avec un noyau beaucoup plus petit.
G. Demecki souligne dans les commentaires que dans les versions 64 bits de JDK, l'option -client
est ignorée pendant de nombreuses années.
Voir commande Windows Java
:
-client
Sélectionne la Java VM HotSpot Client.
Un JDK compatible 64 bits ignore actuellement cette option et utilise à la place la machine virtuelle Java Hotspot Server .
La différence immédiate la plus visible dans les anciennes versions de Java serait la mémoire allouée à une application -client
par opposition à une application -server
. Par exemple, sur mon système Linux, je reçois:
$ 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"
la valeur par défaut est -server
, mais avec l'option -client
, je reçois:
$ 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"
donc avec -server
la plupart des limites de mémoire et des allocations initiales sont beaucoup plus élevées pour cette version Java
.
Toutefois, ces valeurs peuvent changer pour différentes combinaisons d'architecture, de systèmes d'exploitation et de versions Jvm. Les versions récentes de jvm ont supprimé les indicateurs et supprimé de nombreuses distinctions entre serveur et client.
Rappelez-vous aussi que vous pouvez voir tous les détails d'une jvm
en cours d'exécution en utilisant jvisualvm
. Ceci est utile si vous avez des utilisateurs qui ou des modules qui définissent Java_OPTS
ou utilisent des scripts qui modifient les options de ligne de commande. Cela vous permettra également de surveiller, en temps réel, l'utilisation de l'espace heap et permgen, ainsi que de nombreuses autres statistiques.
Une différence que je viens de remarquer est qu'en mode "client", il semble que la machine virtuelle Java restitue de la mémoire inutilisée au système d'exploitation, alors qu'en mode "serveur", une fois que la machine virtuelle a capturé la mémoire, elle ne le laissera pas. retour. C’est ainsi qu’il apparaît de toute façon sur Solaris avec Java6 (en utilisant prstat -Z
pour voir la quantité de mémoire allouée à un processus).
les systèmes -client et -server sont des fichiers binaires différents. Il s’agit essentiellement de deux compilateurs différents (JIT) s’interfaçant avec le même système d’exécution. Le système client est optimal pour les applications nécessitant des temps de démarrage rapides ou une faible empreinte de pas. Le système serveur est optimal pour les applications où les performances globales sont primordiales. En général, le système client convient mieux aux applications interactives telles que les interfaces graphiques
Nous exécutons le code suivant avec les deux commutateurs:
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--) {
}
}
}
Remarque: Le code est compilé une seule fois! Les cours sont les mêmes dans les deux manches!
Avec -client:
Java.exe -client -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
Temps passé: 766
Avec -server:
Java.exe -server -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
Temps passé: 0
Il semble que l'optimazation plus agressive du système serveur supprime la boucle car elle comprend qu'elle n'effectue aucune action!
La documentation en ligne d’Oracle fournit des informations sur Java SE 7.
Sur la page Java - le lanceur d’applications Java pour Windows, l’option -client
est ignorée dans un JDK 64 bits:
Sélectionnez la Java VM HotSpot Client. Un jdk compatible 64 bits ignore actuellement cette option et utilise à la place la VM Java HotSpot Server.
Cependant (pour rendre les choses intéressantes), sous -server
, on lit:
Sélectionnez la Java VM HotSpot Server. Sur un jdk compatible 64 bits, seul le Java HotSpot Server VM est pris en charge, de sorte que l'option -server est implicite. Cela est sujet à changement dans une prochaine version.
La page Détection d'ordinateur de classe serveur fournit des informations sur le choix de VM par le système d'exploitation et l'architecture.
Je ne sais pas dans quelle mesure cela s’applique à JDK 6.
Le serveur IIRC VM optimise le nombre de points d'accès au démarrage afin de l'exécuter plus rapidement, mais prend un peu plus de temps à démarrer et utilise davantage de mémoire. Le client VM diffère l'essentiel de l'optimisation pour permettre un démarrage plus rapide.
Modifier pour ajouter: Voici quelques informations de Sun, ce n'est pas très spécifique mais vous donnera quelques idées.
De Goetz - Java La concurrence en pratique:
- Conseil de débogage: pour les applications serveur, veillez à toujours spécifier le commutateur de ligne de commande JVM
-server
lors de l’appel de la machine virtuelle Java, même pour le développement et les tests. La machine virtuelle Java du serveur effectue davantage d’optimisation que la machine virtuelle client, par exemple en extrayant des variables d’une boucle qui ne sont pas modifiées dans la boucle; Le code qui peut sembler fonctionner dans l'environnement de développement (la machine virtuelle Java cliente) peut être endommagé dans l'environnement de déploiement (la machine virtuelle Java serveur). Par exemple, avions-nous "oublié" de déclarer la variable endormie volatile dans l'extrait 3.4, la machine virtuelle Java du serveur pourrait extraire le test de la boucle (en la transformant en une boucle infinie), mais pas la machine virtuelle cliente. Une boucle infinie apparaissant dans le développement est beaucoup moins coûteuse que celle ne se manifestant que dans la production.Listing 3.4. Compter les moutons.
volatile boolean asleep; ... while (!asleep) countSomeSheep();
Mon emphase. YMMV
IIRC, il implique des stratégies de collecte des ordures. La théorie est qu'un client et un serveur seront différents en termes d'objets de courte durée, ce qui est important pour les algorithmes GC modernes.
Voici un lien en mode serveur. Hélas, ils ne mentionnent pas le mode client.
Voici un lien très complet sur GC en général; c'est un article plus basique . Pas sûr que ce soit l'adresse -serveur vs -client mais c'est du matériel pertinent.
À No Fluff Just Stuff, Ken Sipe et Glenn Vandenburg discutent tous les deux sur ce genre de sujet.
Je n'ai pas remarqué de différence de temps de démarrage entre les 2, mais une amélioration très minime des performances de l'application avec "-server" (serveur Solaris, tout le monde utilisant SunRays pour exécuter l'application). C'était moins de 1,5.
La dernière fois que j’y ai jeté un coup d’œil (et il est vrai que c’était il ya un certain temps), la plus grande différence que j’ai constatée était dans la collecte des ordures ménagères.
IIRC:
Si vous pouvez comparer deux Java machines virtuelles, un client, un serveur à l'aide de l'outil jvisualvm , vous devriez constater une différence dans la fréquence et l'effet du garbage collection, ainsi que dans le nombre de générations.
J'avais une paire de captures d'écran qui montrait très bien la différence, mais je ne peux pas reproduire car j'ai une machine virtuelle Java 64 bits qui implémente uniquement la machine virtuelle du serveur. (Et je ne me soucie pas non plus de télécharger et de modifier la version 32 bits de mon système.)
Cela ne semble plus être le cas, après avoir essayé d'exécuter du code sous Windows avec à la fois des machines virtuelles clientes et clientes, il me semble avoir le même modèle de génération pour les deux ...
Lorsque nous effectuons une migration de la version 1.4 à la version 1.7 ("1.7.0_55"). Ce que nous avons observé ici est qu’il n’existe pas de telles différences dans les valeurs par défaut affectées aux paramètres heapsize | permsize | ThreadStackSize en mode client et serveur.
En passant, ( http://www.Oracle.com/technetwork/Java/ergo5-140223.html ). C'est l'extrait extrait du lien ci-dessus.
initial heap size of 1/64 of physical memory up to 1Gbyte
maximum heap size of ¼ of physical memory up to 1Gbyte
ThreadStackSize est plus élevé dans la version 1.7, lors du forum Open JDK, il y a des discussions qui indiquent que la taille de la trame est un peu plus élevée dans la version 1.7. On pense qu'il est possible de mesurer une différence réelle au moment de l'exécution en fonction du comportement de votre application