source - Diferenças reais entre “java-server” e “java-client”?




jvm open source (8)

Existe alguma diferença prática real entre "java -server" e "java -client"? Tudo o que posso encontrar no site da Sun é um vago "- o servidor começa mais devagar, mas deve ser executado mais rápido". Quais são as diferenças reais? (Usando o JDK 1.6.0_07 atualmente.)

https://code.i-harness.com


A última vez que eu dei uma olhada nisso (e admitidamente já faz um tempo) a maior diferença que notei foi na coleta de lixo.

IIRC:

  • A VM do heap do servidor tem um número diferente de gerações que a VM do Cliente e um algoritmo de coleta de lixo diferente. Isso pode não ser mais verdade
  • A VM do servidor alocará memória e não a liberará para o sistema operacional
  • A VM do servidor usará algoritmos de otimização mais sofisticados e, portanto, terá maiores requisitos de tempo e memória para otimização

Se você puder comparar duas VMs Java, um cliente, um servidor usando a ferramenta jvisualvm , deverá ver uma diferença na frequência e no efeito da coleta de lixo, bem como no número de gerações.

Eu tinha um par de capturas de tela que mostravam a diferença muito bem, mas não consigo reproduzir, já que tenho uma JVM de 64 bits que implementa apenas a VM do servidor. (E eu não posso ser incomodado para baixar e disputar a versão de 32 bits no meu sistema também.)

Isso não parece mais ser o caso, tendo tentado executar algum código em janelas com VMs de servidor e cliente, parece que eu obtive o mesmo modelo de geração para ambos ...


A diferença imediata mais visível em versões mais antigas do Java seria a memória alocada a um -client em oposição a um aplicativo -server . Por exemplo, no meu sistema Linux, recebo:

$ 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 padrão -server , mas com a opção -client eu recebo:

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

Assim, com -server maioria dos limites de memória e alocações iniciais são muito maiores para esta versão de java .

Esses valores podem mudar para diferentes combinações de arquitetura, sistema operacional e versão jvm. Versões recentes do jvm removeram flags e removeram muitas das distinções entre servidor e cliente.

Lembre-se também que você pode ver todos os detalhes de um jvm execução usando jvisualvm . Isso é útil se você tiver usuários que ou módulos que definem JAVA_OPTS ou usam scripts que alteram as opções da linha de comandos. Isso também permitirá que você monitore, em tempo real, o uso do espaço de heap e permgen junto com muitas outras estatísticas.


Ao fazer uma migração de 1.4 para 1.7 ("1.7.0_55") version.The coisa que observamos aqui é, não há tais diferenças nos valores padrão atribuídos aos parâmetros heapsize | permsize | ThreadStackSize no modo cliente e servidor.

By the way, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Este é o trecho extraído do link acima.

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

ThreadStackSize é maior em 1.7, enquanto passa pelo fórum Open JDK, existem discussões que afirmaram que o tamanho do frame é um pouco mais alto na versão 1.7. Acredita-se que a diferença real seja possível medir em tempo de execução com base no seu comportamento de sua aplicação


De Goetz - Java Concorrência na Prática:

  1. Dica de Depuração: Para aplicativos do servidor, certifique-se sempre de especificar a opção de linha de comandos JVM do servidor ao chamar a JVM, mesmo para desenvolvimento e teste . A JVM do servidor executa mais otimização do que a JVM do cliente, como a elevação de variáveis ​​de um loop que não são modificadas no loop; código que pode parecer funcionar no ambiente de desenvolvimento (JVM do cliente) pode quebrar no ambiente de implementação (servidor JVM). Por exemplo, se tivéssemos “esquecido” de declarar a variável adormecida como volátil na Listagem 3.4, a JVM do servidor poderia elevar o teste do loop (transformando-o em um loop infinito), mas a JVM do cliente não o faria . Um loop infinito que aparece no desenvolvimento é muito menos caro do que aquele que só aparece na produção.

Listagem 3.4. Contando ovelhas.

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

Minha ênfase. YMMV


IIRC a VM do servidor faz mais otimizações de hotspot na inicialização, portanto, ele é executado mais rapidamente, mas demora um pouco mais para iniciar e usa mais memória. A VM do cliente adia a maior parte da otimização para permitir uma inicialização mais rápida.

Editar para adicionar: Aqui estão algumas informações da Sun, não são muito específicas, mas fornecem algumas ideias.


IIRC, envolve estratégias de coleta de lixo. A teoria é que um cliente e um servidor serão diferentes em termos de objetos de curta duração, o que é importante para os algoritmos modernos de GC.

Aqui está um link no modo de servidor. Infelizmente, eles não mencionam o modo cliente.

Aqui está um link muito completo sobre GC em geral; Este é um artigo mais básico . Não tenho certeza se qualquer um dos endereços -server vs -client, mas este é um material relevante.

No No Fluff Just Stuff, Ken Sipe e Glenn Vandenburg fazem grandes conversas sobre esse tipo de coisa.


Uma diferença que acabei de notar é que no modo "cliente", parece que a JVM realmente fornece alguma memória não utilizada de volta ao sistema operacional - ao passo que no modo "servidor", uma vez que a JVM agarra a memória, ela não dará de volta. Assim é como aparece no Solaris com o Java6 (usando prstat -Z para ver a quantidade de memória alocada para um processo).


os sistemas -client e -server são binários diferentes. Eles são essencialmente dois compiladores diferentes (JITs) interagindo com o mesmo sistema de tempo de execução. O sistema cliente é ideal para aplicações que precisam de tempos de inicialização rápidos ou pequenas áreas de ocupação, o sistema de servidor é ideal para aplicações em que o desempenho geral é mais importante. Em geral, o sistema cliente é mais adequado para aplicativos interativos, como GUIs

Nós executamos o seguinte código com os dois switches:

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: O código foi compilado apenas uma vez! As aulas são as mesmas nas duas corridas!

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

Com -servidor:
java.exe -server -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Tempo gasto: 0

Parece que o optimazation mais agressivo do sistema do servidor, remova o loop, uma vez que entende que ele não executa qualquer ação!

Reference





jvm-hotspot