มีความแตกต่างในทางปฏิบัติระหว่าง "java -server" และ "java -client" หรือไม่?
ทั้งหมดที่ฉันสามารถหาได้บนเว็บไซต์ของ Sun นั้นค่อนข้างคลุมเครือ
"- เซิร์ฟเวอร์เริ่มช้าลง แต่ควรทำงานได้เร็วขึ้น"
ความแตกต่างที่แท้จริงคืออะไร? (ขณะนี้ใช้ JDK 1.6.0_07)
มีความแตกต่างในทางปฏิบัติระหว่าง "java -server" และ "java -client" หรือไม่?
ทั้งหมดที่ฉันสามารถหาได้บนเว็บไซต์ของ Sun นั้นค่อนข้างคลุมเครือ
"- เซิร์ฟเวอร์เริ่มช้าลง แต่ควรทำงานได้เร็วขึ้น"
ความแตกต่างที่แท้จริงคืออะไร? (ขณะนี้ใช้ JDK 1.6.0_07)
คำตอบ:
นี้จะเชื่อมโยงจริงๆHotSpotและเริ่มต้นค่าตัวเลือก ( Java HotSpot VM ตัวเลือก ) ซึ่งแตกต่างกันระหว่างลูกค้าและการกำหนดค่าเซิร์ฟเวอร์
จากบทที่ 2ของเอกสารทางเทคนิค ( สถาปัตยกรรม Java HotSpot Performance Engine ):
JDK มีสองรสชาติของ VM - ข้อเสนอฝั่งไคลเอ็นต์และ VM ปรับสำหรับแอปพลิเคชันเซิร์ฟเวอร์ โซลูชันทั้งสองนี้ใช้ฐานรหัสสภาพแวดล้อมรันไทม์ Java HotSpot แต่ใช้คอมไพเลอร์ที่แตกต่างกันซึ่งเหมาะสมกับคุณลักษณะด้านประสิทธิภาพที่เป็นเอกลักษณ์ของลูกค้าและเซิร์ฟเวอร์ ความแตกต่างเหล่านี้รวมถึงนโยบายการรวบรวมอินไลน์และค่าเริ่มต้นของฮีป
แม้ว่า Server และ Client VM จะคล้ายกัน แต่ Server VM นั้นได้รับการปรับแต่งเป็นพิเศษเพื่อเพิ่มความเร็วในการทำงานสูงสุด มันมีไว้สำหรับการรันแอพพลิเคชั่นเซิร์ฟเวอร์ที่รันมายาวนานซึ่งต้องการความเร็วในการทำงานที่เร็วที่สุดมากกว่าเวลาเริ่มต้นทำงานที่รวดเร็ว
คอมไพเลอร์ Client VM ทำหน้าที่เป็นการอัพเกรดสำหรับทั้ง Classic Classic และคอมไพเลอร์ just-in-time (JIT) ที่ใช้โดย JDK รุ่นก่อนหน้า ไคลเอนต์ VM เสนอประสิทธิภาพการทำงานขณะปรับปรุงสำหรับแอปพลิเคชันและแอปเพล็ต Java HotSpot Client VM ได้รับการปรับแต่งเป็นพิเศษเพื่อลดเวลาเริ่มต้นแอปพลิเคชันและการปล่อยหน่วยความจำทำให้เหมาะอย่างยิ่งสำหรับสภาพแวดล้อมของไคลเอ็นต์ โดยทั่วไประบบไคลเอนต์จะดีกว่าสำหรับ GUI
ดังนั้นความแตกต่างที่แท้จริงก็เหมือนกันในระดับคอมไพเลอร์:
คอมไพเลอร์ VM ไคลเอนต์ไม่พยายามที่จะดำเนินการเพิ่มประสิทธิภาพที่ซับซ้อนมากขึ้นโดยคอมไพเลอร์ใน Server VM แต่ในการแลกเปลี่ยนมันต้องใช้เวลาน้อยลงในการวิเคราะห์และรวบรวมชิ้นส่วนของรหัส ซึ่งหมายความว่าไคลเอ็นต์ VM สามารถเริ่มทำงานได้เร็วขึ้นและต้องการหน่วยความจำขนาดเล็กลง
Server VM มีคอมไพเลอร์แบบปรับตัวขั้นสูงที่รองรับการเพิ่มประสิทธิภาพประเภทเดียวกันหลายอย่างที่ดำเนินการโดยการปรับแต่งคอมไพเลอร์ C ++ รวมถึงการปรับแต่งบางอย่างที่ไม่สามารถทำได้โดยคอมไพเลอร์แบบดั้งเดิมเช่นการแทรกซึมเชิงรุก นี่เป็นข้อได้เปรียบด้านการแข่งขันและประสิทธิภาพเหนือคอมไพเลอร์แบบคงที่ เทคโนโลยีการปรับให้เหมาะสมแบบปรับได้นั้นมีความยืดหยุ่นอย่างมากในวิธีการของมัน
หมายเหตุ: การเปิดตัวการอัปเดต jdk6 10 (ดูที่หมายเหตุการเผยแพร่การปรับปรุง: การเปลี่ยนแปลงใน 1.6.0_10 ) พยายามปรับปรุงเวลาเริ่มต้น แต่ด้วยเหตุผลที่แตกต่างจากตัวเลือกฮอตสปอต
G. Demeckiชี้ให้เห็นในความคิดเห็นที่ใน JDK รุ่น 64 บิต-client
ตัวเลือกจะถูกละเว้นเป็นเวลาหลายปี
ดูคำสั่งของWindowsjava
:
-client
เลือก Java HotSpot Client VM
ปัจจุบัน JDK ที่มีความสามารถ 64 บิตจะไม่สนใจตัวเลือกนี้และใช้ Java Hotspot Server VMแทน
-client
ตัวเลือกจะถูกละเว้นเป็นเวลาหลายปี
ความแตกต่างที่เห็นได้ชัดเจนที่สุดใน 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
หรือใช้สคริปต์ที่เปลี่ยนตัวเลือกบรรทัดคำสั่ง สิ่งนี้จะช่วยให้คุณสามารถตรวจสอบการใช้พื้นที่ฮีปและเปอร์เรนแบบเรียลไทม์พร้อมสถิติอื่น ๆ อีกมากมาย
ระบบ -client และ -server เป็นไบนารีที่ต่างกัน พวกมันเป็นตัวแปลภาษาที่ต่างกันสองตัว (JITs) ที่เชื่อมต่อกับระบบรันไทม์เดียวกัน ระบบไคลเอนต์เหมาะสมที่สุดสำหรับแอปพลิเคชันที่ต้องการเวลาเริ่มต้นทำงานอย่างรวดเร็วหรือมีขนาดเล็กระบบเซิร์ฟเวอร์เหมาะสำหรับแอปพลิเคชันที่ประสิทธิภาพโดยรวมสำคัญที่สุด โดยทั่วไประบบไคลเอนต์จะเหมาะกว่าสำหรับแอปพลิเคชันแบบโต้ตอบเช่น 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
ดูเหมือนว่าการเพิ่มประสิทธิภาพเชิงรุกของระบบเซิร์ฟเวอร์จะเป็นการลบลูปออกไปเพราะมันเข้าใจดีว่ามันไม่ได้ทำการกระทำใด ๆ !
ข้อแตกต่างอย่างหนึ่งที่ฉันเพิ่งสังเกตเห็นคือในโหมด "ไคลเอนต์" ดูเหมือนว่า JVM จะให้หน่วยความจำที่ไม่ได้ใช้กลับไปยังระบบปฏิบัติการในขณะที่โหมด "เซิร์ฟเวอร์" เมื่อ JVM คว้าหน่วยความจำแล้วมันจะไม่ให้ กลับ. นั่นเป็นวิธีที่ปรากฏบน Solaris ด้วย Java6 ต่อไป (ใช้prstat -Z
เพื่อดูจำนวนหน่วยความจำที่จัดสรรให้กับกระบวนการ)
เอกสารออนไลน์ของ Oracle ให้ข้อมูลบางอย่างสำหรับ Java SE 7
บนjava -หน้าตัวเรียกใช้งานแอปพลิเคชัน Javaสำหรับ Windows -client
ตัวเลือกจะถูกละเว้นใน JDK 64 บิต:
เลือก Java HotSpot Client VM ปัจจุบัน jdk ที่มีความสามารถ 64 บิตจะไม่สนใจตัวเลือกนี้และใช้ Java HotSpot Server VM แทน
อย่างไรก็ตาม (เพื่อให้สิ่งที่น่าสนใจ) ภายใต้-server
มันระบุ:
เลือก Java HotSpot Server VM บน jdk ที่มีความสามารถ 64 บิตสนับสนุน Java HotSpot Server VM เท่านั้นดังนั้นตัวเลือก -server จึงเป็นนัย อาจมีการเปลี่ยนแปลงในการเปิดตัวในอนาคต
เซิร์ฟเวอร์-Class เครื่องตรวจจับหน้าให้ข้อมูลเกี่ยวกับที่ VM จะถูกเลือกโดย OS และสถาปัตยกรรม
ฉันไม่รู้ว่าสิ่งนี้มีผลกับ JDK 6 มากแค่ไหน
จาก Goetz - Java Concurrency ในทางปฏิบัติ:
- แก้จุดบกพร่องเคล็ดลับ: สำหรับการใช้งานเซิร์ฟเวอร์ให้แน่ใจว่าได้เสมอระบุ
-server
สวิตช์บรรทัดคำสั่ง JVM เมื่ออัญเชิญ JVM, แม้กระทั่งสำหรับการพัฒนาและการทดสอบ เซิร์ฟเวอร์ JVM ดำเนินการปรับให้เหมาะสมมากกว่า JVM ไคลเอ็นต์เช่นตัวแปร hoisting จากลูปที่ไม่ได้แก้ไขในลูป รหัสที่อาจปรากฏขึ้นเพื่อทำงานในสภาพแวดล้อมการพัฒนา (ไคลเอนต์ JVM) สามารถแบ่งในสภาพแวดล้อมการปรับใช้ (เซิร์ฟเวอร์ JVM) ตัวอย่างเช่นมีเรา“ลืม” ที่จะประกาศตัวแปรหลับเป็นสารระเหยในรายชื่อ 3.4, เซิร์ฟเวอร์ JVM จะยกการทดสอบออกมาจากวง (เปลี่ยนมันเป็นห่วงอนันต์) แต่ลูกค้า JVM จะไม่ การวนรอบไม่สิ้นสุดที่แสดงในการพัฒนานั้นมีค่าใช้จ่ายน้อยกว่าการแสดงในการผลิตรายชื่อ 3.4 การนับแกะ
volatile boolean asleep; ... while (!asleep) countSomeSheep();
ความสำคัญของฉัน YMMV
IIRC เซิร์ฟเวอร์ VM ทำการเพิ่มประสิทธิภาพฮอตสปอตมากขึ้นเมื่อเริ่มต้นจึงทำงานได้เร็วขึ้น แต่ใช้เวลาเริ่มต้นนานขึ้นและใช้หน่วยความจำเพิ่มขึ้นเล็กน้อย VM ไคลเอนต์ defers ของการปรับให้เหมาะสมที่สุดเพื่อให้เริ่มต้นเร็วขึ้น
แก้ไขเพื่อเพิ่ม: นี่คือข้อมูลบางอย่างจากซันมันไม่ได้เฉพาะเจาะจงมากนัก แต่จะให้แนวคิดบางอย่างแก่คุณ
IIRC มันเกี่ยวข้องกับกลยุทธ์การเก็บขยะ ทฤษฎีคือไคลเอนต์และเซิร์ฟเวอร์จะแตกต่างกันในแง่ของวัตถุที่มีอายุสั้นซึ่งเป็นสิ่งสำคัญสำหรับอัลกอริทึม GC ที่ทันสมัย
นี่คือลิงค์ในโหมดเซิร์ฟเวอร์ อนิจจาพวกเขาไม่ได้พูดถึงโหมดไคลเอนต์
นี่คือลิงค์ทั่ว ๆไปของ GC โดยทั่วไป นี้เป็นบทความพื้นฐานเพิ่มเติม ไม่แน่ใจว่าที่อยู่ - เซิร์ฟเวอร์ vs - ไคลเอนต์ แต่นี่เป็นเนื้อหาที่เกี่ยวข้อง
ที่ No Fluff Just Stuff ทั้ง Ken Sipe และ Glenn Vandenburg พูดถึงเรื่องนี้ได้อย่างยอดเยี่ยม
ฉันไม่ได้สังเกตเห็นความแตกต่างของเวลาเริ่มต้นระหว่าง 2 แต่มีการปรับปรุงประสิทธิภาพการทำงานของแอปพลิเคชั่นน้อยมากด้วย "-server" (เซิร์ฟเวอร์ Solaris ทุกคนที่ใช้ SunRays เพื่อเรียกใช้แอป) ต่ำกว่า 1.5
ครั้งล่าสุดที่ฉันได้ดูเรื่องนี้ (และยอมรับว่ามันเป็นเวลาครู่หนึ่ง) ความแตกต่างที่ใหญ่ที่สุดที่ฉันสังเกตเห็นคือในการเก็บขยะ
IIRC:
หากคุณสามารถเปรียบเทียบสอง java VMs หนึ่งไคลเอ็นต์หนึ่งเซิร์ฟเวอร์โดยใช้เครื่องมือjvisualvmคุณควรเห็นความแตกต่างของความถี่และผลกระทบของการรวบรวมขยะรวมถึงจำนวนรุ่น
ฉันมีภาพหน้าจอที่แสดงความแตกต่างได้ดี แต่ฉันไม่สามารถทำซ้ำได้เนื่องจากฉันมี JVM 64 บิตซึ่งใช้เซิร์ฟเวอร์ VM เท่านั้น (และฉันก็ไม่ต้องกังวลที่จะดาวน์โหลดและบิดรุ่น 32 บิตในระบบของฉันด้วย)
ดูเหมือนจะไม่เป็นเช่นนั้นอีกต่อไปหลังจากลองใช้งานโค้ดบางอย่างบน windows พร้อมทั้งเซิร์ฟเวอร์และไคลเอนต์ VMs ฉันดูเหมือนจะได้รับโมเดลรุ่นเดียวกันสำหรับทั้งสอง ...
เมื่อทำการโอนย้ายจากรุ่น 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 เชื่อว่าความแตกต่างที่แท้จริงอาจเป็นไปได้ในการวัด ณ รันไทม์ตามพฤติกรรมของแอปพลิเคชันของคุณ