Perbedaan nyata antara "java -server" dan "java -client"?


394

Apakah ada perbedaan praktis nyata antara "java -server" dan "java -client"?

Yang bisa saya temukan di situs Sun tidak jelas

"-server mulai lebih lambat tetapi harus berjalan lebih cepat".

Apa perbedaan nyata? (Menggunakan JDK 1.6.0_07 saat ini.)

Jawaban:


368

Ini benar-benar terkait dengan Hotspot dan default nilai opsi ( Java HotSpot VM Options ) yang berbeda antara klien dan konfigurasi server.

Dari Bab 2 whitepaper ( The Java HotSpot Performance Engine Architecture ):

JDK mencakup dua rasa VM - penawaran sisi klien, dan VM yang disetel untuk aplikasi server. Dua solusi ini berbagi basis kode lingkungan runtime Java HotSpot, tetapi menggunakan kompiler yang berbeda yang cocok dengan karakteristik kinerja klien dan server yang unik. Perbedaan-perbedaan ini termasuk kompilasi kebijakan inlining dan heap default.

Meskipun Server dan VM Klien serupa, Server VM telah disesuaikan untuk memaksimalkan kecepatan operasi puncak. Ini dimaksudkan untuk mengeksekusi aplikasi server yang sudah berjalan lama, yang membutuhkan kecepatan operasi secepat mungkin lebih dari waktu start-up cepat atau jejak memori runtime yang lebih kecil.

Kompiler VM Klien berfungsi sebagai pemutakhiran untuk kedua VM Klasik dan kompiler just-in-time (JIT) yang digunakan oleh versi JDK sebelumnya. VM Klien menawarkan peningkatan kinerja run time untuk aplikasi dan applet. Java HotSpot Client VM telah disesuaikan secara khusus untuk mengurangi waktu permulaan aplikasi dan jejak memori, membuatnya sangat cocok untuk lingkungan klien. Secara umum, sistem klien lebih baik untuk GUI.

Jadi perbedaan sebenarnya juga ada pada level kompiler:

Kompiler VM Klien tidak mencoba untuk melakukan banyak optimasi yang lebih kompleks yang dilakukan oleh kompiler di Server VM, tetapi sebagai gantinya, memerlukan lebih sedikit waktu untuk menganalisis dan menyusun sepotong kode. Ini berarti VM Klien dapat memulai lebih cepat dan membutuhkan jejak memori yang lebih kecil.

Server VM berisi kompiler adaptif canggih yang mendukung banyak jenis optimisasi yang sama yang dilakukan dengan mengoptimalkan kompiler C ++, serta beberapa optimisasi yang tidak dapat dilakukan oleh kompiler tradisional, seperti inlining agresif di seluruh invokasi metode virtual. Ini adalah keunggulan kompetitif dan kinerja daripada kompiler statis. Teknologi optimisasi adaptif sangat fleksibel dalam pendekatannya, dan biasanya mengungguli bahkan analisis statis canggih dan teknik kompilasi.

Catatan: Rilis pembaruan jdk6 10 (lihat Perbarui Catatan Rilis: Perubahan pada 1.6.0_10 ) mencoba untuk meningkatkan waktu startup, tetapi untuk alasan yang berbeda dari opsi hotspot, dikemas secara berbeda dengan kernel yang jauh lebih kecil.


G. Demecki menunjukkan dalam komentar bahwa dalam versi JDK 64-bit, -clientopsi ini diabaikan selama bertahun-tahun.
Lihat perintah Windowsjava :

-client

Memilih Java HotSpot Client VM.
JDK berkemampuan 64-bit saat ini mengabaikan opsi ini dan sebagai gantinya menggunakan Java Hotspot Server VM .


7
Pembaruan jdk6 10 dan seterusnya memiliki proses latar belakang menjaga perpustakaan runtime di memori memungkinkan untuk memulai lebih cepat untuk proses baru daripada harus halaman semua dalam permintaan.
Thorbjørn Ravn Andersen

1
Pikir klien saya juga cepat agresif, oh well.
Thorbjørn Ravn Andersen

1
Saya pikir jawaban ini harus diperbarui. Karena pada versi 64-bit JDK -clientopsi diabaikan selama bertahun-tahun.
G. Demecki

@ G.Demecki Tentu: apakah Anda memiliki tautan yang mendokumentasikan bahwa opsi ini sudah usang atau diabaikan?
VonC

1
Tentu. Berikut adalah beberapa dokumentasi untuk Java 7 untuk Windows. Dan ternyata info serupa dapat ditemukan juga di dokumentasi Java 6 .
G. Demecki

90

Perbedaan langsung yang paling terlihat di versi Java yang lebih lama adalah memori yang dialokasikan untuk yang -clientbertentangan dengan -serveraplikasi. Misalnya, pada sistem Linux saya, saya mendapatkan:

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

karena defaultnya -server, tetapi dengan -clientopsi yang saya dapatkan:

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

jadi dengan -serversebagian besar batas memori dan alokasi awal jauh lebih tinggi untuk javaversi ini .

Nilai-nilai ini dapat berubah untuk berbagai kombinasi arsitektur, sistem operasi dan versi jvm. Versi terbaru dari jvm telah menghapus flag dan memindahkan kembali banyak perbedaan antara server dan klien.

Ingat juga bahwa Anda dapat melihat semua rincian yang berjalan jvmmenggunakan jvisualvm. Ini berguna jika Anda memiliki pengguna yang atau modul yang mengatur JAVA_OPTSatau menggunakan skrip yang mengubah opsi baris perintah. Ini juga akan memungkinkan Anda memantau, secara real time, tumpukan dan permgen penggunaan ruang bersama dengan banyak statistik lainnya.


2
Ini memberi saya nomor yang sama pada -server dan -client mode untuk versi java "1.7.0_79" pada CentOS 7 [Java (TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot (TM) 64-Bit Server VM ]
Basil Musa

4
Inilah mengapa saya memberikan jawabannya. Ini bukan tentang nilai-nilai, ini tentang mengaktifkan siapa saja, kapan saja, untuk menemukan jawaban untuk versi jvm spesifik mereka.
Mark Booth

33

sistem -client dan -server adalah binari yang berbeda. Mereka pada dasarnya adalah dua kompiler yang berbeda (JIT) yang berinteraksi dengan sistem runtime yang sama. Sistem klien optimal untuk aplikasi yang membutuhkan waktu startup cepat atau jejak kecil, sistem server optimal untuk aplikasi di mana kinerja keseluruhan yang paling penting. Secara umum sistem klien lebih cocok untuk aplikasi interaktif seperti GUI

masukkan deskripsi gambar di sini

Kami menjalankan kode berikut dengan kedua sakelar:

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

Catatan: Kode hanya dikompilasi satu kali! Kelas-kelasnya sama di kedua run!

Dengan -client:
java.exe -client -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Waktu yang dihabiskan: 766

Dengan -server:
java.exe -server -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Waktu yang dihabiskan: 0

Tampaknya optimisasi yang lebih agresif dari sistem server, hapus loop karena mengerti bahwa itu tidak melakukan tindakan apa pun!

Referensi


33

Satu perbedaan yang baru saja saya perhatikan adalah dalam mode "klien", tampaknya JVM benar-benar mengembalikan memori yang tidak digunakan ke sistem operasi, sedangkan dengan mode "server", begitu JVM mengambil memori, ia tidak akan memberikannya. kembali. Begitulah tampilannya pada Solaris dengan Java6 (gunakan prstat -Zuntuk melihat jumlah memori yang dialokasikan untuk suatu proses).


22

Dokumentasi online Oracle menyediakan beberapa informasi untuk Java SE 7.

Di java - halaman peluncur aplikasi Java untuk Windows, -clientopsi diabaikan dalam JDK 64-bit:

Pilih Java HotSpot Client VM. Jdk mampu 64-bit saat ini mengabaikan opsi ini dan sebagai gantinya menggunakan Java HotSpot Server VM.

Namun (untuk membuat hal-hal menarik), di -serverbawahnya tertulis:

Pilih Java HotSpot Server VM. Pada jdk 64-bit yang mampu hanya Java HotSpot Server VM yang didukung sehingga opsi-server tersirat. Ini dapat berubah dalam rilis mendatang.

The Server-Class Mesin Deteksi halaman memberikan informasi yang VM dipilih oleh OS dan arsitektur.

Saya tidak tahu berapa banyak dari ini berlaku untuk JDK 6.


2
Terima kasih, saya bertanya-tanya kenapa saya tidak melihat klien / jvm.dll di JDK7
Archimedes Trajano

16

Dari Goetz - Java Concurrency dalam Praktek:

  1. Kiat debug: Untuk aplikasi server, pastikan untuk selalu menentukan -serversakelar baris perintah JVM saat menjalankan JVM, bahkan untuk pengembangan dan pengujian . Server JVM melakukan lebih banyak optimasi daripada JVM klien, seperti mengangkat variabel dari loop yang tidak dimodifikasi dalam loop; kode yang mungkin tampak berfungsi di lingkungan pengembangan (klien JVM) dapat memecah di lingkungan penempatan (server JVM). Sebagai contoh, seandainya kita “lupa” untuk mendeklarasikan variabel yang tertidur sebagai volatile pada Listing 3.4, server JVM dapat mengangkat tes keluar dari loop (mengubahnya menjadi loop tak terbatas), tetapi klien JVM tidak mau . Loop tak terbatas yang muncul dalam pengembangan jauh lebih murah daripada yang hanya muncul dalam produksi.

Listing 3.4. Menghitung domba.

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

Penekanan saya. YMMV


15

IIRC server VM melakukan lebih banyak optimasi hotspot saat startup sehingga berjalan lebih cepat tetapi membutuhkan waktu lebih lama untuk memulai dan menggunakan lebih banyak memori. VM klien menolak sebagian besar optimasi untuk memungkinkan startup lebih cepat.

Sunting untuk ditambahkan: Ini beberapa info dari Sun, tidak terlalu spesifik tetapi akan memberi Anda beberapa ide.


5

IIRC, melibatkan strategi pengumpulan sampah. Teorinya adalah bahwa klien dan server akan berbeda dalam hal objek berumur pendek, yang penting untuk algoritma GC modern.

Berikut ini tautannya pada mode server. Sayangnya, mereka tidak menyebutkan mode klien.

Berikut ini adalah tautan yang sangat menyeluruh tentang GC secara umum; ini adalah artikel yang lebih mendasar . Tidak yakin apakah alamat-server vs -client tetapi ini adalah materi yang relevan.

Di No Fluff Just Stuff, baik Ken Sipe dan Glenn Vandenburg melakukan pembicaraan hebat tentang hal semacam ini.


3

Saya tidak melihat adanya perbedaan waktu startup antara 2, tetapi mencatat peningkatan yang sangat minimal dalam kinerja aplikasi dengan "-server" (server Solaris, semua orang menggunakan SunRays untuk menjalankan aplikasi). Itu di bawah 1,5.


6
Tergantung pada apa program Anda lakukan. Untuk beberapa aplikasi intensif prosesor yang melakukan hal yang sama berulang kali, saya perhatikan peningkatan besar (hingga 10x) dengan -server.
Dan Dyer

1
Dan, apakah Anda punya referensi untuk ini? Saya ingin menyelidiki lebih lanjut.
Thorbjørn Ravn Andersen

1
Menjalankan Sunflow dengan server VM jauh lebih cepat daripada klien. sunflow.sourceforge.net
John

1

Terakhir kali saya melihat ini, (dan memang itu beberapa waktu lalu) perbedaan terbesar yang saya perhatikan adalah dalam pengumpulan sampah.

IIRC:

  • Server tumpukan VM memiliki jumlah generasi yang berbeda dari VM Klien, dan algoritma pengumpulan sampah yang berbeda. Ini mungkin tidak benar lagi
  • Server VM akan mengalokasikan memori dan tidak melepaskannya ke OS
  • Server VM akan menggunakan algoritma optimasi yang lebih canggih, dan karenanya memiliki persyaratan waktu dan memori yang lebih besar untuk optimasi

Jika Anda dapat membandingkan dua VM java, satu klien, satu server menggunakan alat jvisualvm , Anda akan melihat perbedaan dalam frekuensi dan efek dari pengumpulan sampah, serta dalam jumlah generasi.

Saya memiliki sepasang tangkapan layar yang menunjukkan perbedaan dengan sangat baik, tetapi saya tidak dapat mereproduksi karena saya memiliki JVM 64 bit yang hanya mengimplementasikan VM server. (Dan saya tidak dapat diganggu untuk mengunduh dan menangani versi 32 bit pada sistem saya juga.)

Ini tampaknya tidak menjadi masalah lagi, setelah mencoba menjalankan beberapa kode pada windows dengan baik server dan VM klien, saya sepertinya mendapatkan model generasi yang sama untuk keduanya ...


1

Saat melakukan migrasi dari versi 1.4 ke 1.7 ("1.7.0_55"). Hal yang kami amati di sini adalah, tidak ada perbedaan dalam nilai default yang ditetapkan untuk heapsize | permsize | threadStackSize parameter dalam mode klien & server.

Ngomong-ngomong, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Ini cuplikan yang diambil dari tautan di atas.

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

ThreadStackSize lebih tinggi di 1,7, sementara melalui forum Open JDK, ada diskusi yang menyatakan ukuran bingkai agak lebih tinggi di versi 1.7. Diyakini perbedaan nyata dapat dimungkinkan untuk mengukur pada saat dijalankan berdasarkan perilaku Anda dari aplikasi Anda

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.