Реальные различия между «Java-сервером» и «Java-клиентом»?

394

Есть ли реальная практическая разница между "java -server" и "java -client"?

Все, что я могу найти на сайте Sun, является расплывчатым

msgstr "-сервер запускается медленнее, но должен работать быстрее".

Каковы реальные различия? (В настоящее время используется JDK 1.6.0_07.)

Пол Томблин
источник

Ответы:

368

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

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

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

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

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

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

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

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

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


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

-client

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

VonC
источник
7
В обновлении jdk6 10 и более поздних версиях есть фоновый процесс, который хранит библиотеки времени выполнения в памяти, что позволяет гораздо быстрее запускать новые процессы, чем выполнять загрузку по требованию.
Турбьёрн Равн Андерсен
1
Думал, клиент вм тоже агрессивно встроен, ну да ладно.
Торбьерн Равн Андерсен
1
Я думаю, что этот ответ должен быть обновлен. Потому что в 64-битных версиях JDK эта -clientопция игнорируется в течение многих лет.
Г. Демецки
@ G.Demecki Конечно: у вас есть ссылка, документирующая, что эта опция устарела или игнорируется?
VonC
1
Конечно. Вот некоторая документация для Java 7 для Windows. И удивительно похожая информация может быть найдена также в Java 6 документации .
Г. Демецки
90

Наиболее заметным непосредственным отличием в старых версиях 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или используют сценарии, которые изменяют параметры командной строки. Это также позволит вам в режиме реального времени отслеживать использование кучи и пространства permgen вместе со многими другими показателями.

Марк Бут
источник
2
Это дает мне те же цифры в режимах -server и -client для java версии 1.7.0_79 в CentOS 7 [Java (TM) SE Runtime Environment (сборка 1.7.0_79-b15) Java HotSpot (TM) 64-битная виртуальная машина сервера ]
Василий Муса
4
Вот почему я дал ответ. Речь идет не о значениях, а о том, чтобы каждый мог в любое время найти ответ для своей конкретной версии jvm.
Марк Бут
33

системы -client и -server - это разные двоичные файлы. По сути, это два разных компилятора (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--) {
        }
    }
}

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

С -client:
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

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

Ссылка

Premraj
источник
33

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

prule
источник
22

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

На java - странице запуска приложений Java для Windows эта -clientопция игнорируется в 64-битном JDK:

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

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

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

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

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

pharsicle
источник
2
Спасибо, мне было интересно, почему я не увидел client / jvm.dll на JDK7
Архимед Траяно,
16

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

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

Листинг 3.4. Считать овец.

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

Мой акцент. YMMV

Адам
источник
15

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

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

Майк Акерс
источник
5

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

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

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

В «No Fluff Just Stuff» и Кен Сипе, и Гленн Ванденбург делают отличные разговоры о подобных вещах.

Майкл Пасха
источник
3

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

Брайан Кноблаух
источник
6
Зависит от того, что делает ваша программа. Для некоторых приложений, интенсивно использующих процессор, которые повторяют одно и то же, я заметил огромные (до 10 раз) улучшения с -server.
Дэн Дайер
1
Дэн, у тебя есть ссылка на это? Я хотел бы исследовать дальше.
Турбьерн Равн Андерсен
1
Запуск Sunflow с виртуальной машиной сервера НАМНОГО быстрее, чем клиент. sunflow.sourceforge.net
Джон
1

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

IIRC:

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

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

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

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

Brice
источник
1

При переходе с версии 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. Считается, что реальную разницу можно измерить во время выполнения в зависимости от вашего поведения приложения

Nuwan Arambage
источник