Pregunta

¿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.)

¿Fue útil?

Solución

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

De Capítulo 2 del documento técnico ( La arquitectura del motor de rendimiento de Java HotSpot ):

  

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 operativa más rápida posible más que un tiempo de inicio rápido o una huella de memoria de tiempo de ejecución más pequeña.

     

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 de 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 mediante la optimización de 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 jdk6 update 10 (consulte Notas de la versión de actualización: los cambios en 1.6.0_10 ) intentaron mejorar el tiempo de inicio, pero por una razón diferente a las opciones de punto de acceso, se empaquetaron de manera diferente con un núcleo mucho más pequeño.


G. Demecki señala en los comentarios de que en las versiones de 64 bits de JDK, la opción -client se ignora durante muchos años.
Ver Windows java command :

-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 Java Hotspot Server .

Otros consejos

La diferencia inmediata más visible en las versiones anteriores de Java sería la memoria asignada a una -client en lugar de una aplicación -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"

ya que su valor predeterminado es -server , pero con la opción -client 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 -server la mayoría de los límites de memoria y las asignaciones iniciales son mucho más altos para esta versión java .

Sin embargo, estos valores pueden cambiar para diferentes combinaciones de arquitectura, sistemas operativos y versiones 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 un jvm en ejecución usando jvisualvm . Esto es útil si tiene usuarios o módulos que configuran JAVA_OPTS o usa scripts que cambian las opciones de la línea de comandos. Esto también le permitirá monitorear, en tiempo real, el uso del espacio heap y permgen junto con muchas otras estadísticas.

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

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 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 compiló solo una vez! ¡Las clases son iguales en ambas carreras!

Con -client:
 java.exe -client -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
 Tiempo dedicado: 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

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

En la java - el iniciador de aplicaciones Java para Windows , la opción -client 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), en -server dice:

  

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 Detección de máquinas de clase de servidor proporciona información en el que VM está seleccionada por el sistema operativo y la arquitectura.

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

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ífico pero te dará algunas ideas.

De Goetz: concurrencia de Java en la práctica:

  
      
  1. Sugerencia de depuración: para aplicaciones de servidor, asegúrese de especificar siempre el conmutador de línea de comandos JVM -server cuando invoque la JVM, incluso para   desarrollo y pruebas . El servidor JVM realiza más optimización   que la JVM del cliente, como levantar variables de un bucle que son   no modificado en el bucle; código que parece funcionar en el   El entorno de desarrollo (JVM del cliente) puede interrumpirse en la implementación   entorno (servidor JVM). Por ejemplo, si nos hubiéramos olvidado # 8220; declarar   la variable dormida como volátil en el Listado 3.4, la JVM del servidor podría   izar la prueba fuera del bucle (convirtiéndola en un bucle infinito), pero   el cliente JVM no lo haría . Un bucle infinito que aparece en   el desarrollo es mucho menos costoso que uno que solo aparece en   producción.
  2.   
     

Listado 3.4. Contando ovejas.

     

  booleano volátil dormido;   ...   mientras (! dormido)      countSomeSheep ();

Mi énfasis. YMMV

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 de 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.

No he notado 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.

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
  • La VM del servidor 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 me molesto en descargar y disputar la versión de 32 bits también en mi sistema).

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 ...

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 hay tales diferencias en los valores predeterminados asignados a los parámetros heapsize | permsize | ThreadStackSize en el cliente & amp; modo 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 a través del 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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top