2011-03-14 33 views
10

Ứng dụng của chúng tôi đang đọc dữ liệu rất nhanh qua các cổng TCP/IP trong Java. Chúng tôi đang sử dụng thư viện NIO với một Ổ cắm không chặn và Bộ chọn để cho biết sự sẵn sàng để đọc. Trung bình, thời gian xử lý tổng thể để đọc và xử lý dữ liệu đọc là dưới một phần nghìn giây. Tuy nhiên, chúng tôi thường xuyên thấy các gai 10-20 mili giây. (chạy trên Linux).Vấn đề hiệu suất Socket Java TCP/IP

Sử dụng tcpdump chúng tôi có thể thấy sự khác biệt về thời gian giữa việc đọc tcpdump của 2 thông điệp kín đáo và so sánh điều đó với thời gian đăng ký của chúng tôi. Chúng tôi thấy tcpdump dường như không có độ trễ, trong khi ứng dụng có thể hiển thị 20 mili giây. Chúng tôi khá chắc chắn đây không phải GC, vì nhật ký GC cho thấy hầu như không có GC đầy đủ, và trong JDK 6 (từ những gì tôi hiểu), GC mặc định là song song, vì vậy nó không nên tạm dừng các luồng ứng dụng (trừ khi làm đầy đủ GC). Có vẻ như có sự chậm trễ cho phương pháp Selector.select(0) của Java để trả lại sự sẵn sàng để đọc, bởi vì ở lớp TCP, dữ liệu đã sẵn sàng để đọc (và tcpdump đang đọc nó).

Thông tin bổ sung: tại tải cao điểm, chúng tôi xử lý khoảng 6.000 x 150 byte trung bình cho mỗi thư hoặc khoảng 900 MB mỗi giây.

+0

Như @Jim Lewis đã nói, có khả năng mất thời gian để chuyển ngữ cảnh và bạn không thể kiểm soát cách Java triển khai NIO nội bộ. Hoàn toàn có thể là JVM bổ sung thêm một số chi phí mà bạn sẽ không thể loại bỏ. Điều đó nói rằng, không nhìn thấy nhiều dữ liệu hơn, tôi không thể đưa ra giải pháp. –

+2

Vâng - Tôi đã dọn dẹp các câu trả lời không được chấp nhận của mình. Tôi không muốn bất cứ ai nghĩ rằng tôi không coi trọng thời gian họ đã trả lời câu hỏi. –

+0

Tôi có thể giúp cung cấp một số chi tiết về jvm, kernel/distro, phần cứng – Matt

Trả lời

4

Bộ sưu tập eden vẫn phải tạm dừng STW để 20ms có thể hoàn toàn bình thường tùy thuộc vào hành vi phân bổ & kích thước/kích thước heap của tập hợp trực tiếp.

+0

Sau khi thử nghiệm nhiều hơn, hồ sơ, vv Chúng tôi đã kết luận rằng GC, thậm chí GC nhỏ bằng cách sử dụng ParallelGC dường như để ngăn chặn tất cả mọi thứ. Các khoản tạm dừng trong khoảng từ 2 ms đến 20 ms. Làm cho mã hiệu quả hơn có thể làm giảm số chu kỳ GC và thậm chí là cả thời gian GC. Vì vậy, điều này ảnh hưởng đến độ trễ của truyền thông ổ cắm, và có vẻ như không có gì có thể được thực hiện. Chúng tôi đã kiểm tra RTLinux, và do đó không có cải tiến lớn. Chúng tôi bắt đầu điều tra Java thời gian thực, nhưng không nghĩ đó là con đường tốt nhất (chi phí khôn ngoan và phức tạp). –

+0

MOST của CMS là song song. Chỉ có một phần rất nhỏ STW .. mà dường như là 20ms bạn nhìn thấy (bạn có thể buộc nó trở lại các bản ghi GC).Nếu bạn muốn tạm dừng có thể dự đoán được, bạn có thể xem xét bộ thu G1, nhưng bạn sẽ có nhiều tạm dừng tổng thể hơn so với CMS. – bwawok

3

Mã Java của bạn có đang chạy dưới RTLinux hay một số bản phân phối khác với khả năng lập lịch thời gian thực cứng không? Nếu không, 10-20 msec của jitter trong thời gian xử lý có vẻ hoàn toàn hợp lý, và mong đợi.

+0

Tôi sẽ không mong đợi 10-20ms jitter cho bất kỳ hộp hiện đại mà không phải là quá tải nghiêm trọng, thậm chí một vài 00us là rất nhiều. – Matt

+0

@Matt: Như tôi đã hiểu, 10 ms là một giá trị tiêu biểu cho độ dài của một lần trong một bộ lập lịch không gian thời gian thực của Linux/x86. Vì vậy, nếu cuộc gọi select() tạo ra CPU, nó có thể dễ dàng mất nhiều thời gian cho công việc đó để được lên lịch lại. –

+0

Tôi đang cố hiểu nhận xét của bạn - chúng tôi đang chạy Red Hat Enterprise 5.4. 2 CPU. Máy chủ yếu là đang chạy ứng dụng Java và MySQL. Việc tắt cập nhật cơ sở dữ liệu hoặc các quá trình khác trên máy chủ dường như không ảnh hưởng đến độ trễ tăng đột biến. Bạn có nghĩ rằng chúng ta có thể giải quyết vấn đề này bằng cách chuyển sang phân phối RTLinux. –

1

Từ tcpdump faq:

KHI là một gói thời gian đóng dấu? LÀM THẾ NÀO CHÍNH XÁC LÀ TEM THỜI GIAN?

Trong hầu hết các hệ điều hành trên đó tcpdump và libpcap chạy, các gói dữ liệu là thời gian đóng dấu như là một phần của quá trình điều khiển thiết bị giao diện mạng, hoặc ngăn xếp mạng, xử lý nó. Điều này có nghĩa là gói không phải là thời gian đóng dấu ngay khi nó đến tại giao diện mạng; sau khi gói đến tại giao diện mạng , sẽ có một sự chậm trễ cho đến khi một ngắt được giao hoặc giao diện mạng được thăm dò (ví dụ, giao diện mạng có thể không làm gián đoạn dẫn chương trình ngay lập tức - người lái xe có thể được thiết lập lên để thăm dò giao diện nếu số lượng lưu lượng truy cập mạng là , để giảm số số lần ngắt và xử lý nhiều gói hơn cho mỗi gián đoạn), và sẽ bị trì hoãn thêm tại số tại thời điểm bắt đầu ngắt và xử lý dấu thời gian là được tạo.

Vì vậy, tỷ lệ là dấu thời gian được tạo trong lớp nhân đặc quyền và 20ms bị mất là chuyển ngữ cảnh trở lại không gian người dùng và sang Java và logic bộ chọn mạng JVM. Nếu không có phân tích nhiều hơn về hệ thống như một toàn thể tôi không nghĩ rằng nó có thể làm cho một lựa chọn khẳng định nguyên nhân.

+0

Đã nói về câu trả lời của bạn với những người khác trong văn phòng của chúng tôi. Họ chỉ ra rằng các gai chúng ta đang thấy là lên đến 40 ms. sự khác biệt từ tcpdump. Điều đó có vẻ là quá lớn của một sự khác biệt để được giải thích bởi các bên trên. Đó thực sự là hành vi "spiking" không phù hợp mà chúng tôi đang cố sửa. –

+1

Bạn có chắc chắn đã loại bỏ các hoạt động GC như một nguyên nhân không? Tỷ lệ phần trăm yêu cầu dẫn đến "tăng đột biến" là bao nhiêu? –

2

Tôi gặp sự cố tương tự trong dịch vụ java mà tôi đang thực hiện. Khi gửi cùng một yêu cầu liên tục từ máy khách, máy chủ sẽ chặn tại cùng một vị trí trong luồng trong 25-35ms. Tắt thuật toán của Nagle trong ổ cắm đã sửa lỗi này cho tôi. Điều này có thể được thực hiện bằng cách gọi setTcpNoDelay (true) trên Socket. Điều này có thể dẫn đến sự tắc nghẽn mạng gia tăng vì ACK giờ đây sẽ được gửi riêng biệt như gói. Xem http://en.wikipedia.org/wiki/Nagle%27s_algorithm để biết thêm thông tin về thuật toán của Nagle.

Các vấn đề liên quan