Sự khác biệt thực sự giữa java java -server và và java java -client?


394

Có sự khác biệt thực tế nào giữa "java -server" và "java -client" không?

Tất cả những gì tôi có thể tìm thấy trên trang web của Sun là mơ hồ

"-Server bắt đầu chậm hơn nhưng sẽ chạy nhanh hơn".

Sự khác biệt thực sự là gì? (Hiện đang sử dụng JDK 1.6.0_07.)

Câu trả lời:


368

Điều này thực sự được liên kết với HotSpot và các giá trị tùy chọn mặc định ( Tùy chọn VM HotSpot ) khác nhau giữa cấu hình máy khách và máy chủ.

Từ Chương 2 của whitepaper ( Kiến trúc công cụ hiệu suất Java HotSpot ):

JDK bao gồm hai hương vị của VM - cung cấp phía máy khách và VM được điều chỉnh cho các ứng dụng máy chủ. Hai giải pháp này chia sẻ cơ sở mã môi trường thời gian chạy Java HotSpot, nhưng sử dụng các trình biên dịch khác nhau phù hợp với các đặc tính hiệu năng riêng biệt của máy khách và máy chủ. Những khác biệt này bao gồm chính sách biên dịch và mặc định heap.

Mặc dù Máy chủ và Máy khách VM tương tự nhau, Máy chủ VM đã được điều chỉnh đặc biệt để tối đa hóa tốc độ hoạt động cao nhất. Nó được thiết kế để thực thi các ứng dụng máy chủ chạy dài, cần tốc độ hoạt động nhanh nhất có thể hơn thời gian khởi động nhanh hoặc dấu chân bộ nhớ thời gian chạy nhỏ hơn.

Trình biên dịch VM máy khách phục vụ như là một bản nâng cấp cho cả trình biên dịch VM cổ điển và trình biên dịch chỉ trong thời gian (JIT) được sử dụng bởi các phiên bản trước của JDK. Client VM cung cấp hiệu năng thời gian chạy được cải thiện cho các ứng dụng và applet. Máy khách Java HotSpot đã được điều chỉnh đặc biệt để giảm thời gian khởi động ứng dụng và dung lượng bộ nhớ, làm cho nó đặc biệt phù hợp với môi trường máy khách. Nói chung, hệ thống máy khách tốt hơn cho GUI.

Vì vậy, sự khác biệt thực sự cũng là ở cấp độ trình biên dịch:

Trình biên dịch VM máy khách không cố thực hiện nhiều tối ưu hóa phức tạp hơn được trình biên dịch thực hiện trong Server VM, nhưng đổi lại, nó cần ít thời gian hơn để phân tích và biên dịch một đoạn mã. Điều này có nghĩa là VM máy khách có thể khởi động nhanh hơn và yêu cầu dung lượng bộ nhớ nhỏ hơn.

Server VM chứa trình biên dịch thích ứng nâng cao hỗ trợ nhiều loại tối ưu hóa giống nhau được thực hiện bằng cách tối ưu hóa trình biên dịch C ++, cũng như một số tối ưu hóa không thể thực hiện được bởi các trình biên dịch truyền thống, chẳng hạn như xâm lấn qua các yêu cầu phương thức ảo. Đây là một lợi thế cạnh tranh và hiệu suất so với trình biên dịch tĩnh. Công nghệ tối ưu hóa thích ứng rất linh hoạt trong cách tiếp cận của nó, và thường vượt trội hơn cả các kỹ thuật phân tích và biên dịch tĩnh tiên tiến.

Lưu ý: Việc phát hành bản cập nhật jdk6 10 (xem Cập nhật ghi chú phát hành: Thay đổi trong 1.6.0_10 ) đã cố gắng cải thiện thời gian khởi động, nhưng vì một lý do khác với các tùy chọn hotspot, được đóng gói khác với hạt nhân nhỏ hơn nhiều.


G. Demecki chỉ ra trong các ý kiến rằng trong các phiên bản JDK 64 bit, -clienttùy chọn này bị bỏ qua trong nhiều năm.
Xem lệnh Windowsjava :

-client

Chọn máy khách Java HotSpot Client.
Một JDK có khả năng 64 bit hiện đang bỏ qua tùy chọn này và thay vào đó sử dụng máy chủ Java Hotspot Server VM .


7
jdk6 update 10 trở đi có một quy trình nền giữ các thư viện thời gian chạy trong bộ nhớ cho phép khởi động nhanh hơn nhiều cho các tiến trình mới hơn là phải trang tất cả theo yêu cầu.
Thorbjørn Ravn Andersen

1
Nghĩ khách vm cũng nội tuyến ráo riết, ôi thôi.
Thorbjørn Ravn Andersen

1
Tôi nghĩ rằng câu trả lời này nên được cập nhật. Bởi vì trên các phiên bản 64 bit của JDK, -clienttùy chọn bị bỏ qua trong nhiều năm.
G. Demecki

@ G.Demecki Chắc chắn: bạn có một tài liệu liên kết rằng tùy chọn này đã lỗi thời hoặc bị bỏ qua?
VonC

1
Chắc chắn rồi. Đây là một số thông tin cho Java 7 cho Windows. Và đáng ngạc nhiên là một thông tin tương tự cũng có thể được tìm thấy trong tài liệu Java 6 .
G. Demecki

90

Sự khác biệt rõ ràng nhất có thể thấy rõ trong các phiên bản Java cũ hơn sẽ là bộ nhớ được phân bổ -clientcho một -serverứng dụng trái ngược với ứng dụng. Chẳng hạn, trên hệ thống Linux của tôi, tôi nhận được:

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

như mặc định -server, nhưng với -clienttùy chọn tôi nhận được:

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

Vì vậy, với -serverhầu hết các giới hạn bộ nhớ và phân bổ ban đầu cao hơn nhiều cho javaphiên bản này .

Tuy nhiên, các giá trị này có thể thay đổi cho các kết hợp khác nhau về kiến ​​trúc, hệ điều hành và phiên bản jvm. Các phiên bản gần đây của jvm đã xóa cờ và di chuyển lại nhiều điểm khác biệt giữa máy chủ và máy khách.

Hãy nhớ rằng bạn có thể thấy tất cả các chi tiết của một hoạt động đang jvmsử dụng jvisualvm. Điều này hữu ích nếu bạn có người dùng hoặc mô-đun thiết lập JAVA_OPTShoặc sử dụng tập lệnh thay đổi tùy chọn dòng lệnh. Điều này cũng sẽ cho phép bạn theo dõi, trong thời gian thực, sử dụng không gian heappermgen cùng với rất nhiều số liệu thống kê khác.


2
Nó cung cấp cho tôi các số tương tự trên các chế độ máy chủ và máy chủ cho phiên bản java "1.7.0_79" trên Môi trường thời gian chạy SE của CentOS 7 [Java (TM) (xây dựng 1.7.0_79-b15) ]
Basil Musa

4
Đây là lý do tại sao tôi cung cấp câu trả lời. Đó không phải là về các giá trị, mà là cho phép bất cứ ai, bất cứ lúc nào, tìm câu trả lời cho phiên bản jvm cụ thể của họ.
Đánh dấu gian hàng

33

hệ thống -client và -erver là các nhị phân khác nhau. Chúng cơ bản là hai trình biên dịch (JIT) khác nhau giao tiếp với cùng một hệ thống thời gian chạy. Hệ thống máy khách là tối ưu cho các ứng dụng cần thời gian khởi động nhanh hoặc dấu chân nhỏ, hệ thống máy chủ là tối ưu cho các ứng dụng trong đó hiệu suất tổng thể là quan trọng nhất. Nói chung, hệ thống máy khách phù hợp hơn cho các ứng dụng tương tác như GUI

nhập mô tả hình ảnh ở đây

Chúng tôi chạy mã sau với cả hai công tắc:

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

Lưu ý: Mã chỉ được biên dịch một lần! Các lớp giống nhau trong cả hai lần chạy!

Với -client:
java.exe -client-classpath C: \ mywork \ class com.blogspot.sdoulger.LoopTest
Thời gian sử dụng: 766

Với -server:
java.exe -server-classpath C: \ mywork \ class com.blogspot.sdoulger.LoopTest
Thời gian sử dụng: 0

Có vẻ như sự tối ưu hóa mạnh mẽ hơn của hệ thống máy chủ, hãy loại bỏ vòng lặp vì nó hiểu rằng nó không thực hiện bất kỳ hành động nào!

Tài liệu tham khảo


33

Một điểm khác biệt mà tôi vừa nhận thấy là ở chế độ "máy khách", có vẻ như JVM thực sự đưa một số bộ nhớ không sử dụng trở lại hệ điều hành, trong khi với chế độ "máy chủ", một khi JVM lấy bộ nhớ, nó sẽ không cung cấp cho nó trở lại. Đó là cách nó xuất hiện trên Solaris với Java6 (sử dụng prstat -Zđể xem lượng bộ nhớ được phân bổ cho một quy trình).


22

Tài liệu trực tuyến của Oracle cung cấp một số thông tin cho Java SE 7.

Trên java - trang trình khởi chạy ứng dụng Java cho Windows, -clienttùy chọn này bị bỏ qua trong JDK 64 bit:

Chọn máy khách Java HotSpot. Một jdk có khả năng 64 bit hiện đang bỏ qua tùy chọn này và thay vào đó sử dụng máy chủ Java HotSpot Server VM.

Tuy nhiên (để làm cho mọi thứ thú vị), theo -servernó nêu:

Chọn máy chủ Java HotSpot Server. Trên jdk có khả năng 64 bit, chỉ có Java HotSpot Server VM được hỗ trợ để tùy chọn -server được ẩn. Điều này có thể thay đổi trong một bản phát hành trong tương lai.

Các máy chủ-Class Machine Detection trang cung cấp thông tin trên đó VM được chọn theo hệ điều hành và kiến trúc.

Tôi không biết bao nhiêu trong số này áp dụng cho JDK 6.


2
Cảm ơn, tôi đã tự hỏi tại sao tôi không thấy khách hàng / jvm.dll trên JDK7
Archimedes Trajano

16

Từ Goetz - Java đồng thời trong thực tế:

  1. Mẹo gỡ lỗi: Đối với các ứng dụng máy chủ, đảm bảo luôn luôn chỉ định -serverchuyển đổi dòng lệnh JVM khi gọi JVM, ngay cả để phát triển và thử nghiệm . JVM của máy chủ thực hiện tối ưu hóa nhiều hơn JVM của máy khách, chẳng hạn như các biến tích hợp trong một vòng lặp không được sửa đổi trong vòng lặp; mã có thể hoạt động trong môi trường phát triển (máy khách JVM) có thể bị hỏng trong môi trường triển khai (máy chủ JVM). Ví dụ, chúng ta đã quên mất việc khai báo biến khi ngủ là biến động trong Liệt kê 3.4, JVM của máy chủ có thể đưa thử nghiệm ra khỏi vòng lặp (biến nó thành một vòng lặp vô hạn), nhưng JVM của máy khách thì không . Một vòng lặp vô hạn xuất hiện trong quá trình phát triển ít tốn kém hơn nhiều so với vòng lặp chỉ xuất hiện trong sản xuất.

Liệt kê 3.4. Đếm cừu.

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

Tôi nhấn mạnh. YMMV


15

IIRC máy chủ VM thực hiện tối ưu hóa nhiều điểm nóng hơn khi khởi động để nó chạy nhanh hơn nhưng mất nhiều thời gian hơn để bắt đầu và sử dụng nhiều bộ nhớ hơn. VM máy khách trì hoãn hầu hết các tối ưu hóa để cho phép khởi động nhanh hơn.

Chỉnh sửa để thêm: Đây là một số thông tin từ Sun, nó không cụ thể lắm nhưng sẽ cung cấp cho bạn một số ý tưởng.


5

IIRC, nó liên quan đến các chiến lược thu gom rác. Lý thuyết là một máy khách và máy chủ sẽ khác nhau về các đối tượng có thời gian tồn tại ngắn, điều này rất quan trọng đối với các thuật toán GC hiện đại.

Đây là một liên kết về chế độ máy chủ. Than ôi, họ không đề cập đến chế độ khách hàng.

Đây là một liên kết rất kỹ lưỡng về GC nói chung; đây là một bài viết cơ bản hơn . Không chắc chắn nếu địa chỉ -server vs -client nhưng đây là tài liệu có liên quan.

Tại No Fluff Just Stuff, cả Ken Sipe và Glenn Vandenburg đều có những cuộc nói chuyện tuyệt vời về loại điều này.


3

Tôi đã không nhận thấy bất kỳ sự khác biệt nào về thời gian khởi động giữa 2 người, nhưng đã đạt được sự cải thiện rất nhỏ về hiệu suất ứng dụng với "-server" (máy chủ Solaris, mọi người sử dụng SunRays để chạy ứng dụng). Đó là dưới 1,5.


6
Phụ thuộc vào những gì chương trình của bạn đang làm. Đối với một số ứng dụng chuyên sâu về bộ xử lý liên tục làm điều tương tự, tôi đã nhận thấy những cải tiến lớn (lên đến 10 lần) với -server.
Dan Dyer

1
Dan, bạn có một tài liệu tham khảo về điều này? Tôi muốn điều tra thêm.
Thorbjørn Ravn Andersen

1
Chạy Sunflow với máy chủ VM nhanh hơn NHIỀU máy khách. sunflow.sourceforge.net
John

1

Lần trước tôi đã xem xét điều này, (và phải thừa nhận rằng đó là một thời gian trước) sự khác biệt lớn nhất tôi nhận thấy là trong bộ sưu tập rác.

IIRC:

  • VM heap máy chủ có số lượng thế hệ khác nhau so với VM máy khách và thuật toán thu gom rác khác nhau. Điều này có thể không còn đúng nữa
  • VM máy chủ sẽ phân bổ bộ nhớ và không giải phóng nó cho HĐH
  • VM máy chủ sẽ sử dụng các thuật toán tối ưu hóa tinh vi hơn và do đó có yêu cầu về thời gian và bộ nhớ lớn hơn để tối ưu hóa

Nếu bạn có thể so sánh hai máy ảo java, một máy khách, một máy chủ bằng công cụ jvisualvm , bạn sẽ thấy sự khác biệt về tần suất và hiệu quả của bộ sưu tập rác, cũng như về số lượng thế hệ.

Tôi đã có một cặp ảnh chụp màn hình cho thấy sự khác biệt thực sự tốt, nhưng tôi không thể sao chép vì tôi có một JVM 64 bit chỉ thực hiện VM máy chủ. (Và tôi không thể bận tâm tải xuống và đánh bại phiên bản 32 bit trên hệ thống của mình.)

Điều này dường như không còn là vấn đề nữa, vì đã thử chạy một số mã trên windows với cả máy chủ và máy khách VM, tôi dường như có được mô hình thế hệ giống nhau cho cả ...


1

Khi thực hiện di chuyển từ phiên bản 1.4 sang 1.7 ("1.7.0_55"). Điều mà chúng tôi quan sát được ở đây là, không có sự khác biệt nào về giá trị mặc định được gán cho các tham số heapsize | permsize | ThreadStackSize trong chế độ máy khách và máy chủ.

Nhân tiện, ( http://www.oracle.com/technetwork/java/ergo5-140223.html ). Đây là đoạn trích được lấy từ liên kết trên.

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

ThreadStackSize cao hơn trong 1.7, trong khi đi qua diễn đàn Open JDK, có những cuộc thảo luận cho biết kích thước khung hình có phần cao hơn trong phiên bản 1.7. Người ta tin rằng sự khác biệt thực sự có thể được đo lường trong thời gian chạy dựa trên hành vi của ứng dụng của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.