¿Diferencias reales entre "java -server" y "java -client"?

394

¿Hay alguna diferencia práctica real entre "java -server" y "java -client"?

Todo lo que puedo encontrar en el sitio de Sun es vago

"-server comienza más lento pero debería ejecutarse más rápido".

¿Cuáles son las diferencias reales? (Usando JDK 1.6.0_07 actualmente.)

Paul Tomblin
fuente

Respuestas:

368

Esto realmente está vinculado a HotSpot y los valores de opción predeterminados ( Opciones de Java de HotSpot VM ) que difieren entre la configuración del cliente y el servidor.

Del Capítulo 2 del documento técnico ( The Java HotSpot Performance Engine Architecture ):

El JDK incluye dos tipos de VM: una oferta del lado del cliente y una VM ajustada para aplicaciones de servidor. Estas dos soluciones comparten la base de código del entorno de tiempo de ejecución de Java HotSpot, pero utilizan diferentes compiladores que se adaptan a las características de rendimiento claramente únicas de los clientes y servidores. Estas diferencias incluyen la política de compilación en línea y los valores predeterminados del montón.

Aunque las máquinas virtuales del servidor y del cliente son similares, la máquina virtual del servidor se ha ajustado especialmente para maximizar la velocidad máxima de funcionamiento. Está destinado a ejecutar aplicaciones de servidor de larga ejecución, que necesitan la velocidad de operación más rápida posible más que un tiempo de inicio rápido o una menor huella de memoria en tiempo de ejecución.

El compilador de VM del cliente sirve como una actualización tanto para la VM clásica como para los compiladores just-in-time (JIT) utilizados por versiones anteriores del JDK. Client VM ofrece un rendimiento de tiempo de ejecución mejorado para aplicaciones y applets. La máquina virtual Java HotSpot Client se ha ajustado especialmente para reducir el tiempo de inicio de la aplicación y la huella de memoria, lo que la hace especialmente adecuada para entornos de clientes. En general, el sistema del cliente es mejor para las GUI.

Entonces, la verdadera diferencia también está en el nivel del compilador:

El compilador de VM del cliente no intenta ejecutar muchas de las optimizaciones más complejas realizadas por el compilador en la VM del servidor, pero a cambio, requiere menos tiempo para analizar y compilar un fragmento de código. Esto significa que la VM del cliente puede iniciarse más rápido y requiere una huella de memoria más pequeña.

La VM del servidor contiene un compilador adaptativo avanzado que admite muchos de los mismos tipos de optimizaciones realizadas optimizando los compiladores de C ++, así como algunas optimizaciones que los compiladores tradicionales no pueden hacer, como la inserción agresiva en invocaciones de métodos virtuales. Esta es una ventaja competitiva y de rendimiento sobre los compiladores estáticos. La tecnología de optimización adaptativa es muy flexible en su enfoque y generalmente supera incluso las técnicas avanzadas de análisis estático y compilación.

Nota: El lanzamiento de la actualización 10 de jdk6 (ver Notas de la versión de actualización: Cambios en 1.6.0_10 ) trató de mejorar el tiempo de inicio, pero por una razón diferente a las opciones de punto de acceso, se empaquetó de manera diferente con un núcleo mucho más pequeño.


G. Demecki señala en los comentarios que en las versiones de 64 bits de JDK, la -clientopción se ignora durante muchos años.
Ver comando de Windowsjava :

-client

Selecciona la máquina virtual Java HotSpot Client.
Un JDK con capacidad de 64 bits actualmente ignora esta opción y, en su lugar, utiliza la máquina virtual del servidor de Java Hotspot .

VonC
fuente
77
La actualización 10 de jdk6 y posteriores tienen un proceso en segundo plano que mantiene las bibliotecas de tiempo de ejecución en la memoria, lo que permite un inicio mucho más rápido para los nuevos procesos que tener que paginar todo bajo demanda.
Thorbjørn Ravn Andersen
1
Pensé que el cliente también estaba en línea agresivamente, oh bueno.
Thorbjørn Ravn Andersen
1
Creo que esta respuesta debería actualizarse. Porque en las versiones de JDK de 64 bits, la -clientopción se ignora durante muchos años.
G. Demecki
@ G.Demecki Claro: ¿tiene un enlace que documente que esta opción es obsoleta o ignorada?
VonC
1
Por supuesto. Aquí hay alguna documentación para Java 7 para Windows. Y sorprendentemente, una información similar se puede encontrar también en la documentación de Java 6 .
G. Demecki
90

La diferencia inmediata más visible en las versiones anteriores de Java sería la memoria asignada a una aplicación -clienten lugar de a otra -server. Por ejemplo, en mi sistema Linux, obtengo:

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

como está predeterminado -server, pero con la -clientopción obtengo:

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

así que con la -servermayoría de los límites de memoria y las asignaciones iniciales son mucho más altas para esta javaversión.

Sin embargo, estos valores pueden cambiar para diferentes combinaciones de arquitectura, sistema operativo y versión jvm. Las versiones recientes de jvm han eliminado las banderas y han eliminado muchas de las distinciones entre servidor y cliente.

Recuerde también que puede ver todos los detalles de una ejecución jvmusando jvisualvm. Esto es útil si tiene usuarios que o módulos que establecen JAVA_OPTSo usan secuencias de comandos que cambian las opciones de la línea de comandos. Esto también le permitirá monitorear, en tiempo real, el uso del espacio de almacenamiento dinámico y permanente junto con muchas otras estadísticas.

Mark Booth
fuente
2
Me da los mismos números en los modos de servidor y cliente para la versión java "1.7.0_79" en CentOS 7 [Java (TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot (TM) 64-Bit Server VM ]
Basil Musa
44
Es por eso que proporcioné la respuesta. No se trata de los valores, se trata de permitir que cualquier persona, en cualquier momento, encuentre la respuesta para su versión jvm específica.
Mark Booth
33

Los sistemas -client y -server son binarios diferentes. Son esencialmente dos compiladores diferentes (JIT) que interactúan con el mismo sistema de tiempo de ejecución. El sistema cliente es óptimo para aplicaciones que necesitan tiempos de inicio rápidos o pequeñas huellas, el sistema de servidor es óptimo para aplicaciones donde el rendimiento general es más importante. En general, el sistema cliente es más adecuado para aplicaciones interactivas como las GUI

ingrese la descripción de la imagen aquí

Ejecutamos el siguiente código con ambos interruptores:

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: ¡ El código se ha compilado solo una vez! ¡Las clases son iguales en ambas carreras!

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

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

Parece que la optimización más agresiva del sistema del servidor, elimina el bucle, ya que entiende que no realiza ninguna acción.

Referencia

Premraj
fuente
33

Una diferencia que acabo de notar es que en el modo "cliente", parece que la JVM devuelve algo de memoria no utilizada al sistema operativo, mientras que con el modo "servidor", una vez que la JVM toma la memoria, no le dará espalda. Así es como aparece en Solaris con Java6 de todos modos (usando prstat -Zpara ver la cantidad de memoria asignada a un proceso).

Prule
fuente
22

La documentación en línea de Oracle proporciona información para Java SE 7.

En java, la página de inicio de aplicaciones Java para Windows, la -clientopción se ignora en un JDK de 64 bits:

Seleccione la máquina virtual Java HotSpot Client. Un jdk con capacidad de 64 bits actualmente ignora esta opción y, en su lugar, utiliza la máquina virtual Java HotSpot Server.

Sin embargo (para hacer las cosas interesantes), debajo -serverdice:

Seleccione la máquina virtual Java HotSpot Server. En un jdk con capacidad de 64 bits, solo se admite la máquina virtual Java HotSpot Server, por lo que la opción -server está implícita. Esto está sujeto a cambios en una versión futura.

La página de detección de máquina de clase de servidor proporciona información sobre qué VM está seleccionada por el sistema operativo y la arquitectura.

No sé cuánto de esto se aplica a JDK 6.

pharsicle
fuente
2
Gracias, me preguntaba por qué no vi un cliente / jvm.dll en JDK7
Archimedes Trajano
16

De Goetz - Concurrencia de Java en la práctica:

  1. Sugerencia de depuración: para aplicaciones de servidor, asegúrese de especificar siempre el -servermodificador de línea de comando JVM cuando invoque la JVM, incluso para el desarrollo y las pruebas . La JVM del servidor realiza más optimización que la JVM del cliente, como el levantamiento de variables de un bucle que no se modifica en el bucle; el código que parece funcionar en el entorno de desarrollo (JVM del cliente) puede romperse en el entorno de implementación (JVM del servidor). Por ejemplo, si hubiéramos "olvidado" declarar la variable dormida como volátil en el Listado 3.4, la JVM del servidor podría levantar la prueba del bucle (convirtiéndola en un bucle infinito), pero la JVM del cliente no lo haría . Un ciclo infinito que aparece en el desarrollo es mucho menos costoso que uno que solo aparece en la producción.

Listado 3.4. Contando ovejas.

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

Mi énfasis YMMV

Adán
fuente
15

IIRC, la máquina virtual del servidor, realiza más optimizaciones de punto de acceso al inicio, por lo que se ejecuta más rápido, pero tarda un poco más en iniciarse y usa más memoria. La máquina virtual cliente difiere la mayor parte de la optimización para permitir un inicio más rápido.

Editar para agregar: Aquí hay información de Sun, no es muy específica, pero le dará algunas ideas.

Mike Akers
fuente
5

IIRC, involucra estrategias de recolección de basura. La teoría es que un cliente y un servidor serán diferentes en términos de objetos de corta duración, lo cual es importante para los algoritmos GC modernos.

Aquí hay un enlace en modo servidor. Por desgracia, no mencionan el modo cliente.

Aquí hay un enlace muy completo sobre GC en general; Este es un artículo más básico . No estoy seguro si la dirección -server vs -client pero este es material relevante.

En No Fluff Just Stuff, tanto Ken Sipe como Glenn Vandenburg hacen grandes conversaciones sobre este tipo de cosas.

Michael Easter
fuente
3

No noté ninguna diferencia en el tiempo de inicio entre los 2, pero registró una mejora muy mínima en el rendimiento de la aplicación con "-server" (servidor Solaris, todos los que usan SunRays para ejecutar la aplicación). Eso fue menos de 1.5.

Brian Knoblauch
fuente
66
Depende de lo que esté haciendo tu programa. Para algunas aplicaciones intensivas en procesador que hacen lo mismo repetidamente, he notado mejoras enormes (hasta 10 veces) con -server.
Dan Dyer,
1
Dan, ¿tienes alguna referencia a esto? Me gustaría investigar más a fondo.
Thorbjørn Ravn Andersen
1
Ejecutar Sunflow con el servidor VM es MUCHO más rápido que el cliente. sunflow.sourceforge.net
John
1

La última vez que eché un vistazo a esto (y es cierto que fue hace un tiempo) la mayor diferencia que noté fue en la recolección de basura.

IIRC:

  • La VM del montón del servidor tiene un número diferente de generaciones que la VM del cliente y un algoritmo de recolección de basura diferente. Puede que esto ya no sea cierto
  • La máquina virtual del servidor asignará memoria y no la liberará al sistema operativo
  • El servidor VM utilizará algoritmos de optimización más sofisticados y, por lo tanto, tendrá mayores requisitos de tiempo y memoria para la optimización

Si puede comparar dos máquinas virtuales Java, un cliente y un servidor utilizando la herramienta jvisualvm , debería ver una diferencia en la frecuencia y el efecto de la recolección de basura, así como en el número de generaciones.

Tenía un par de capturas de pantalla que mostraban la diferencia realmente bien, pero no puedo reproducirlo ya que tengo una JVM de 64 bits que solo implementa la VM del servidor. (Y no puedo molestarme en descargar y discutir la versión de 32 bits en mi sistema también).

Este ya no parece ser el caso, después de haber intentado ejecutar algún código en Windows con máquinas virtuales de servidor y cliente, parece que obtengo el mismo modelo de generación para ambos ...

brice
fuente
1

Al realizar una migración de la versión 1.4 a 1.7 ("1.7.0_55"). Lo que observamos aquí es que no existen tales diferencias en los valores predeterminados asignados a los parámetros heapsize | permsize | ThreadStackSize en modo cliente y servidor.

Por cierto, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Este es el fragmento tomado del enlace anterior.

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

ThreadStackSize es más alto en 1.7, mientras que en el foro Open JDK, hay discusiones que indican que el tamaño del marco es algo más alto en la versión 1.7. Se cree que la diferencia real podría ser posible medir en tiempo de ejecución en función del comportamiento de su aplicación

Nuwan Arambage
fuente