"Java -server" ve "java -client" arasında gerçek bir pratik fark var mı?
Sun'ın sitesinde bulabileceğim tek şey belirsiz
msgstr "-server yavaş başlar ancak daha hızlı çalışmalıdır".
Gerçek farklar nelerdir? (Şu anda JDK 1.6.0_07 kullanılıyor.)
"Java -server" ve "java -client" arasında gerçek bir pratik fark var mı?
Sun'ın sitesinde bulabileceğim tek şey belirsiz
msgstr "-server yavaş başlar ancak daha hızlı çalışmalıdır".
Gerçek farklar nelerdir? (Şu anda JDK 1.6.0_07 kullanılıyor.)
Yanıtlar:
Bu gerçekten HotSpot ve istemci ve sunucu yapılandırması arasında farklılık gösteren varsayılan seçenek değerlerine ( Java HotSpot VM Seçenekleri ) bağlıdır.
Teknik belgenin 2. Bölümünden ( Java HotSpot Performans Motoru Mimarisi ):
JDK, VM'nin iki çeşidi içerir - bir istemci tarafı teklifi ve sunucu uygulamaları için ayarlanmış bir VM. Bu iki çözüm Java HotSpot çalışma zamanı ortam kodu tabanını paylaşır, ancak istemcilerin ve sunucuların benzersiz performans özelliklerine uygun farklı derleyiciler kullanır. Bu farklılıklar, derleme satır içi ilkesi ve yığın varsayılanlarını içerir.
Sunucu ve İstemci VM'leri benzer olsa da, Sunucu VM'si en yüksek çalışma hızını en üst düzeye çıkarmak için özel olarak ayarlanmıştır. Mümkün olan en hızlı çalışma hızına hızlı bir başlangıç süresinden veya daha küçük çalışma zamanı bellek ayak izinden daha fazlasını gerektiren uzun süreli sunucu uygulamalarını yürütmek için tasarlanmıştır.
İstemci VM derleyicisi, hem Klasik VM hem de JDK'nın önceki sürümleri tarafından kullanılan tam zamanında (JIT) derleyiciler için yükseltme görevi görür. İstemci VM, uygulamalar ve uygulamalar için geliştirilmiş çalışma süresi performansı sunar. Java HotSpot Client VM, uygulama başlatma süresini ve bellek kapladığı alanı azaltmak için özel olarak ayarlanmıştır, bu da özellikle istemci ortamları için çok uygundur. Genel olarak, istemci sistemi GUI'ler için daha iyidir.
Yani gerçek fark derleyici seviyesinde:
İstemci VM derleyicisi, Sunucu VM'sinde derleyici tarafından gerçekleştirilen daha karmaşık optimizasyonların çoğunu yürütmeye çalışmaz, ancak karşılığında bir kod parçasını analiz etmek ve derlemek için daha az zaman gerektirir. Bu, İstemci VM'nin daha hızlı başlayabileceği ve daha az bellek alanı gerektirdiği anlamına gelir.
Sunucu VM'si, C ++ derleyicilerini optimize ederek gerçekleştirilen aynı optimizasyon türlerinin çoğunu ve sanal yöntem çağrılarında agresif satırlama gibi geleneksel derleyiciler tarafından gerçekleştirilemeyen bazı optimizasyonları destekleyen gelişmiş bir uyarlanabilir derleyici içerir. Bu, statik derleyicilere göre rekabetçi ve performans avantajıdır. Uyarlanabilir optimizasyon teknolojisi yaklaşımında çok esnektir ve tipik olarak gelişmiş statik analiz ve derleme tekniklerinden bile daha iyi performans gösterir.
Not: jdk6 10 güncellemesi (bkz. Güncelleme Sürüm Notları: 1.6.0_10'daki değişiklikler ), başlatma süresini iyileştirmeye çalıştı, ancak etkin nokta seçeneklerinden farklı bir nedenden dolayı, çok daha küçük bir çekirdekle farklı şekilde paketlendi.
G. Demecki işaret açıklamalarda bulunan JDK 64 bit sürümlerinde, -client
seçenek yıllarca göz ardı edilir. Windows komutuna
bakın :java
-client
Java HotSpot İstemci VM'sini seçer.
64 bit özellikli bir JDK şu anda bu seçeneği yoksayar ve bunun yerine Java Hotspot Server VM'sini kullanır .
-client
seçenek yıllarca yok sayılır.
Java'nın eski sürümlerindeki en görünür ani fark, -client
bir -server
uygulamanın aksine a'ya ayrılan bellek olacaktır . Örneğin, Linux sistemimde:
$ 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"
varsayılan olarak -server
, ama -client
ben seçeneği ile :
$ 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"
bu nedenle -server
bellek sınırlarının çoğu ve ilk tahsisler bu java
sürüm için çok daha yüksektir .
Ancak bu değerler mimarinin, işletim sisteminin ve jvm sürümünün farklı kombinasyonları için değişebilir. Jvm'nin son sürümleri bayrakları kaldırmış ve sunucu ile istemci arasındaki ayrımların çoğunu yeniden taşımıştır.
Eğer bir çalışan tüm ayrıntılarını görmek olduğu da unutmayın jvm
kullanarak jvisualvm
. Bu, JAVA_OPTS
komut satırı seçeneklerini değiştiren komut dosyaları ayarlayan veya kullanan kullanıcılarınız veya modülleriniz varsa kullanışlıdır . Bu, gerçek zamanlı olarak yığın ve permgen alanı kullanımını diğer birçok istatistikle birlikte izlemenizi sağlar.
-client ve -server sistemleri farklı ikili dosyalardır. Bunlar aslında aynı çalışma zamanı sistemine arabirim oluşturan iki farklı derleyicidir (JIT). İstemci sistemi, hızlı başlatma süreleri veya küçük ayak izleri gerektiren uygulamalar için en uygunudur, sunucu sistemi genel performansın en önemli olduğu uygulamalar için en uygunudur. Genel olarak istemci sistemi GUI'ler gibi etkileşimli uygulamalar için daha uygundur
Her iki anahtarla aşağıdaki kodu çalıştırıyoruz:
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--) {
}
}
}
Not: Kod yalnızca bir kez derlenmiştir! Her iki koşuda da sınıflar aynı!
-Client:
java.exe -client -classpath ile C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Harcanan zaman: 766
-Server:
java.exe -server -classpath ile C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Harcanan zaman: 0
Sunucu sisteminin daha agresif optimizasyonu, herhangi bir eylem gerçekleştirmediğini anladığı için döngüyü kaldırın!
Fark ettiğim bir fark, "istemci" modunda, JVM'nin aslında işletim sistemine bazı kullanılmamış bellek verdiği, "sunucu" modunda ise, JVM belleği yakaladığında, vermediği geri. Yine de Solaris'te Java6 ile nasıl göründüğü ( prstat -Z
bir işleme ayrılan bellek miktarını görmek için kullanarak ).
Oracle'ın çevrimiçi belgeleri Java SE 7 için bazı bilgiler sağlar.
Açık java - Java uygulaması başlatıcısı Windows için sayfanın -client
seçenek 64-bit JDK göz ardı edilir:
Java HotSpot İstemci VM'sini seçin. 64-bit özellikli bir jdk şu anda bu seçeneği yoksayar ve bunun yerine Java HotSpot Sunucu VM'sini kullanır.
Ancak (işleri ilginç hale getirmek için) altında -server
:
Java HotSpot Sunucusu VM'sini seçin. 64-bit özellikli bir jdk'de sadece Java HotSpot Sunucu VM'si desteklenir, böylece -server seçeneği örtük olur. Bu, gelecekteki bir sürümde değişime tabidir.
Sunucu Sınıfı Makinesi Algılama sayfa VM OS ve mimarisinden seçildiği hakkında bilgi verir.
Bunun ne kadarının JDK 6 için geçerli olduğunu bilmiyorum.
Goetz'den - Uygulamada Java Eşzamanlılığı:
- Hata ayıklama ipucu: Sunucu uygulamaları için,
-server
JVM'yi çağırırken geliştirme ve test için bile her zaman JVM komut satırı anahtarını belirttiğinizden emin olun . Sunucu JVM, döngüde değiştirilmeyen bir döngüden değişkenleri kaldırma gibi istemci JVM'den daha fazla optimizasyon gerçekleştirir; geliştirme ortamında (istemci JVM) çalışıyor gibi görünen kod dağıtım ortamında (sunucu JVM) bozulabilir. Örneğin, Değişken Listeleme 3.4'te değişken olarak uykuda olduğunu bildirmeyi “unutmuş olsaydık” , sunucu JVM testi döngüden kaldırabilir (sonsuz döngüye çevirebilir), ancak istemci JVM istemezdi . Gelişmede ortaya çıkan sonsuz bir döngü, sadece üretimde ortaya çıkandan çok daha az maliyetlidir.Liste 3.4. Koyun saymak.
volatile boolean asleep; ... while (!asleep) countSomeSheep();
Vurgu. YMMV
IIRC sunucu VM başlangıçta daha fazla etkin nokta optimizasyonu yapar, böylece daha hızlı çalışır, ancak başlatılması biraz daha uzun sürer ve daha fazla bellek kullanır. İstemci VM, daha hızlı başlatma için optimizasyonun çoğunu savunur.
Eklemek için düzenleyin: İşte Sun'ın bazı bilgileri , çok spesifik değil ama size bazı fikirler verecektir.
IIRC, çöp toplama stratejilerini içerir. Teori, bir istemci ve sunucunun modern GC algoritmaları için önemli olan kısa ömürlü nesneler açısından farklı olacağıdır.
İşte sunucu modunda bir bağlantı . Ne yazık ki, müşteri modundan bahsetmiyorlar.
Genel olarak GC üzerinde çok kapsamlı bir bağlantı ; bu daha temel bir makale . Her iki adres -server vs -client olup olmadığından emin değilim ancak bu ilgili bir materyal.
No Fluff Just Stuff'da hem Ken Sipe hem de Glenn Vandenburg bu tür şeyler hakkında harika konuşmalar yapıyor.
Ben 2 arasında başlangıç zamanı herhangi bir fark fark ettim, ama "-server" (Solaris sunucusu, uygulamayı çalıştırmak için SunRays kullanan herkes) ile uygulama performansında çok az bir iyileşme saat. Bu 1.5'in altındaydı.
Son kez bu bir göz vardı, (ve kuşkusuz bir süre geri oldu) fark büyük fark çöp toplama oldu.
IIRC:
Jvisualvm aracını kullanarak iki java VM'si , bir istemci, bir sunucu karşılaştırabiliyorsanız , çöp toplama sıklığı ve etkisi ile nesillerin sayısında bir fark görmelisiniz.
Farkı gerçekten gösteren bir çift ekran görüntüsü vardı, ancak yalnızca sunucu VM'sini uygulayan 64 bit JVM'ye sahip olduğum için çoğaltılamıyorum. (Ve 32 bit sürümünü sistemime de indirip rahatsız edemiyorum.)
Bu artık böyle görünmüyor, hem sunucu hem de istemci VM'leri ile pencerelerde bazı kod çalıştırmayı denedikten sonra, her ikisi için de aynı nesil modeli alıyor gibiyim ...
1.4'ten 1.7'ye ("1.7.0_55") sürüm geçişi yaparken. Burada gözlemlediğimiz şey, istemci ve sunucu modunda heapsize | permsize | ThreadStackSize parametrelerine atanan varsayılan değerlerde böyle bir fark yoktur.
Bu arada, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Bu, yukarıdaki linkten alınan snippet'tir.
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'de daha yüksek, Open JDK forumundan geçerken 1.7 versiyonunda kare boyutunun biraz daha yüksek olduğunu belirten tartışmalar var. Uygulamanızdaki davranışınıza göre çalışma zamanında gerçek farkın ölçülebileceğine inanılmaktadır.