Реальные различия между "java-server" и "java -client"?

Есть ли реальная практическая разница между "java-server" и "java -client"? Все, что я могу найти на сайте Sun, - это неопределенный "-сервер запускается медленнее, но должен работать быстрее". Каковы реальные различия? (С использованием JDK 1.6.0_07 в настоящее время.)

Ответ 1

Это действительно связано с HotSpot и значениями по умолчанию (Параметры Java HotSpot VM), которые отличаются между конфигурацией клиента и сервера.

Из Глава 2 технической документации (Архитектура движка производительности Java HotSpot):

JDK включает в себя два варианта виртуальной машины - клиентское предложение и виртуальную машину, настроенную для серверных приложений. Эти два решения совместно используют базовую среду кода среды исполнения Java HotSpot, но используют разные компиляторы, которые подходят для совершенно уникальных характеристик производительности клиентов и серверов. Эти различия включают в себя компиляцию, определяющую политику и значения по умолчанию для кучи.

Несмотря на то, что серверная и клиентская виртуальные машины схожи, виртуальная машина сервера специально настроена для максимальной максимальной рабочей скорости. Он предназначен для выполнения долгосрочных серверных приложений, для которых требуется максимальная скорость работы быстрее, чем быстрое время запуска или меньшая занимаемая память.

Компилятор клиентской VM служит обновлением как для классической виртуальной машины, так и для компиляторов "точно в срок" (JIT), используемых предыдущими версиями JDK. Клиентская VM обеспечивает улучшенную производительность во время выполнения приложений и апплетов. Клиентская виртуальная машина Java HotSpot специально настроена для сокращения времени запуска приложений и использования памяти, что делает его особенно подходящим для клиентских сред. В целом, клиентская система лучше подходит для графических интерфейсов.

Таким образом, реальная разница также находится на уровне компилятора:

Компилятор клиентской VM не пытается выполнить многие из более сложных оптимизаций, выполняемых компилятором в VM сервера, но взамен требуется меньше времени для анализа и компиляции фрагмента кода. Это означает, что клиентская VM может запускаться быстрее и требует меньшего объема памяти.

VM сервера содержит усовершенствованный адаптивный компилятор, который поддерживает многие из тех же типов оптимизаций, которые выполняются при оптимизации компиляторов С++, а также некоторые оптимизации, которые не могут быть выполнены традиционными компиляторами, такие как агрессивная встраивание вызовов виртуальных методов. Это конкурентное преимущество и преимущество перед статическими компиляторами. Адаптивная технология оптимизации очень гибка в своем подходе и обычно превосходит даже продвинутые методы статического анализа и компиляции.

Примечание. Релиз обновления jdk6 10 (см. Примечания к выпуску обновлений: изменения в 1.6.0_10) попытался улучшить время запуска, но для по другой причине, чем опции "горячей точки", по-разному упакованы с гораздо меньшим ядром.


G. Demecki указывает в комментариях, что в 64-битных версиях JDK опция -client игнорируется в течение многих лет.
См. команда Windows java:

-client

Выбор клиентской виртуальной машины Java HotSpot.
64-разрядная версия JDK в настоящее время игнорирует этот параметр и вместо этого использует VM Hotspot Server VM.

Ответ 2

Наиболее очевидной непосредственной разницей в более старых версиях Java будет память, выделенная для -client, а не для приложения -server. Например, в моей системе Linux я получаю:

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

поскольку по умолчанию он равен -server, но с параметром -client я получаю:

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

поэтому с -server большая часть ограничений памяти и начальных распределений намного выше для этой версии java.

Эти значения могут изменяться для разных комбинаций архитектуры, операционной системы и версии jvm. Последние версии jvm удалили флаги и повторно переместили многие различия между сервером и клиентом.

Помните также, что вы можете просмотреть все детали работы jvm с помощью jvisualvm. Это полезно, если у вас есть пользователи, которые или модули, которые устанавливают JAVA_OPTS, или используют сценарии, которые изменяют параметры командной строки. Это также позволит вам контролировать в режиме реального времени использование кучи и пространства сменного пространства, а также множество других характеристик.

Ответ 3

Единственное отличие, которое я только что заметил, заключается в том, что в режиме "клиент", похоже, JVM фактически возвращает некоторую неиспользуемую память в операционную систему, тогда как в режиме "сервер", когда JVM захватывает память, t вернуть его. То, как оно появляется в Solaris с Java6 в любом случае (используя prstat -Z, чтобы увидеть объем памяти, выделенной для процесса).

Ответ 4

Онлайн-документация Oracles предоставляет некоторую информацию для Java SE 7.

На странице java - Java application launcher для Windows параметр -client игнорируется в 64-разрядном JDK:

Выберите виртуальную машину клиента Java HotSpot. 64-разрядная версия jdk в настоящее время игнорирует эту опцию и вместо этого использует виртуальную машину Java HotSpot.

Однако (чтобы сделать что-то интересное), в разделе -server говорится:

Выберите виртуальную машину Java HotSpot. В 64-разрядной версии jdk поддерживается только VM Java HotSpot Server, поэтому опция -server неявно. Это может быть изменено в будущей версии.

На странице "Обнаружение машины на сервере" страница содержит информацию о том, какая VM выбрана ОС и архитектурой.

Я не знаю, насколько это относится к JDK 6.

Ответ 5

системы -клиент и -сервер представляют собой разные двоичные файлы. Это, по существу, два разных компилятора (JIT), взаимодействующие с одной и той же системой времени исполнения. Клиентская система оптимальна для приложений, которым требуется быстрое время запуска или небольшие отпечатки, серверная система оптимальна для приложений, где общая производительность является наиболее важной. В целом клиентская система лучше подходит для интерактивных приложений, таких как GUI

введите описание изображения здесь

Мы запускаем следующий код с помощью обоих переключателей:

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

Примечание: Код компилируется только один раз! Классы одинаковы в обоих прогонах!

С -клиентом:
 java.exe -client -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
 Время, проведенное: 766

С -server:
 java.exe -server -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
 Время: 0

Кажется, что более агрессивная оптимизация серверной системы удаляет цикл, поскольку он понимает, что он не выполняет никаких действий!

Ссылка

Ответ 6

IIRC, сервер VM делает больше хот-спотов при запуске, поэтому он работает быстрее, но занимает немного больше времени для запуска и использует больше памяти. Клиентская VM отключает большую часть оптимизации, чтобы ускорить запуск.

Изменить, чтобы добавить: Вот некоторая информация от Sun, это не очень специфично, но даст вам несколько идей.

Ответ 7

Из Goetz - Java Concurrency на практике:

  1. Отладка: для серверных приложений обязательно указывайте ключ командной строки -server JVM при вызове JVM, даже для разработка и тестирование. Сервер JVM выполняет большую оптимизацию чем клиентская JVM, такая как перемещение переменных из цикла, которые не изменен в цикле; код, который может работать в среда разработки (клиентская JVM) может ломаться при развертывании среда (сервер JVM). Например, если бы мы "забыли" объявить переменная, спящая как volatile в листинге 3.4, , JVM сервера может вытащите тест из цикла (превращая его в бесконечный цикл), но клиентская JVM не будет. Бесконечный цикл, который появляется в разработка намного менее дорогостоящая, чем та, которая появляется только в производство.

Листинг 3.4. Подсчет овец.

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

Мой акцент. YMMV

Ответ 8

IIRC, он включает в себя стратегии сбора мусора. Теория состоит в том, что клиент и сервер будут отличаться в терминах короткоживущих объектов, что важно для современных алгоритмов GC.

Вот ссылка в режиме сервера. Увы, они не упоминают клиентский режим.

Вот очень подробная ссылка на GC вообще; это более простая статья. Не уверен, что либо адрес-сервер vs -client, но это релевантный материал.

В "No Fluff Just Stuff" Кен Сип и Гленн Ванденбург прекрасно проводят такие переговоры.

Ответ 9

Я не заметил никакой разницы во времени запуска между двумя, но очень медленно улучшил производительность приложения с помощью "-сервера" (сервер Solaris, каждый из которых использует SunRays для запуска приложения). Это было менее 1,5.

Ответ 10

В прошлый раз, когда я посмотрел на это (и, по общему признанию, это было время назад), самая большая разница, которую я заметил, была в сборке мусора.

IIRC:

  • Куча серверов VM имеет различное количество поколений, чем клиентская VM, и другой алгоритм сбора мусора. Это может быть неверно больше
  • VM сервера будет выделять память и не выводить ее на ОС
  • Виртуальная машина сервера использует более сложные алгоритмы оптимизации и, следовательно, имеет больше требований к времени и памяти для оптимизации.

Если вы можете сравнить две виртуальные машины Java, один клиент, один сервер, используя инструмент jvisualvm, вы должны увидеть разницу в частоту и эффект сбора мусора, а также в количестве поколений.

У меня была пара скриншотов, которая показала разницу действительно хорошо, но я не могу воспроизвести, поскольку у меня 64-разрядная JVM, которая только реализует виртуальную машину сервера. (И я не могу беспокоиться о том, чтобы загрузить и прервать 32-битную версию в моей системе.)

Это, похоже, уже не так, попробовав запустить некоторый код в Windows с виртуальными машинами на сервере и на клиенте, я, похоже, получаю одну и ту же модель генерации для обоих...

Ответ 11

При выполнении перехода с версии 1.4 на 1.7 ( "1.7.0_55" ). Мы наблюдаем здесь, что нет никаких различий в значениях по умолчанию, назначенных параметрам heapsize | permsize | ThreadStackSize в режиме клиента и сервера.

Кстати, (http://www.oracle.com/technetwork/java/ergo5-140223.html). Это фрагмент, взятый из приведенной выше ссылки.

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

ThreadStackSize выше в 1.7, проходя через форум Open JDK, есть обсуждения, в которых размер кадра несколько выше в версии 1.7. Считается, что реальная разница может быть измерена во время выполнения на основе вашего поведения вашего приложения.