2010-09-09 22 views
8

Tôi có một ứng dụng Java có khối lượng lớn xử lý tải nhất quán 50000msgs/giây. Nó được điều chỉnh cho thông lượng cao bằng cách sử dụng các cài đặt sau:Tại sao thời gian GC tăng đều đặn trên một ứng dụng Java có khối lượng lớn chạy dài?

-Xmx3g -Xms3g -XX: NewSize = 2g -Xss128k -XX: SurvivorRatio = 6 -XX: TargetSurvivorRatio = 90 -XX: + UseParallelGC -XX: ParallelGCThreads = 12 -XX: + UseParallelOldGC -XX: + HeapDumpOnOutOfMemoryError

Tôi thấy rằng thời gian GC trẻ tăng đều từ 50ms khi nó bắt đầu 200ms vào cuối ngày, mặc dù tần số GC vẫn giữ nguyên.

Nếu tôi thử chạy tương tự bằng cách sử dụng bộ thu ParNewGC, thời gian GC tăng lên với tốc độ nhanh hơn nhiều. Có ai có bất kỳ suy nghĩ về vấn đề này?

+0

Ngày càng tệ hơn vào ngày hôm sau, tức là bạn sẽ khởi động lại ứng dụng nhiều hơn 200 m mỗi ngày? – JoseK

+0

Một dự đoán, nhưng không phải đây chỉ là một tác dụng phụ của NewSize thực sự lớn? GC-ing trên 2 gig của các đối tượng có vẻ như nó sẽ mất một thời gian. – wds

Trả lời

3

Nếu bạn bị rò rỉ bộ nhớ hoặc bộ nhớ cache trong bộ nhớ đang dần sử dụng bộ nhớ ngày càng nhiều, chúng sẽ có tác dụng làm cho GC thực hiện công việc theo dõi các đối tượng có thể truy cập.

khả năng khác là:

  • Bạn có một rò rỉ bộ nhớ phi heap, và đó là kết quả trong việc tăng phân trang; tức là sao chép các trang bộ nhớ vật lý vào đĩa và quay lại.

  • Một số quy trình bên ngoài đang tiêu thụ lượng bộ nhớ ngày càng tăng, dẫn đến tăng phân trang.

  • Bản chất của các đối tượng được tạo trong thế hệ trẻ đang thay đổi theo thời gian sao cho cần nhiều công việc hơn để theo dõi các đối tượng có thể truy cập. Nó có thể chỉ đơn giản là một tỷ lệ lớn hơn trong số họ sống sót qua bộ sưu tập đầu tiên.

+0

Tôi đã kiểm tra rằng không có rò rỉ bộ nhớ, các đồ thị của các thế hệ trẻ, có tuổi thọ và già đều đều định kỳ. –

2

Nó có thể là một sự kết hợp của nhiều yếu tố:

  • Một rò rỉ bộ nhớ thực. (Các đối tượng vẫn được tham chiếu một cách tình cờ)
  • Các đối tượng khác hoặc có thể phân phối khác nhau của các đối tượng giữa các gc-pool.
  • Heap lớn hơn. Lô thời gian gc và kích thước heap.
  • Phân mảnh bộ nhớ. Trên cấp độ hệ điều hành và/hoặc heap java, tùy thuộc vào jvm.

Tại sao bạn không vẽ số đối tượng, kích thước heap và thời gian gc. (sử dụng một công cụ, hoặc bằng cách quering MBeans) Một cốt truyện nên cho bạn biết xu hướng; tăng, giảm hoặc tuyến tính và sẽ giúp bạn xác định xem có rò rỉ hay không. Nếu có thể, cũng đổ một số thống kê từ chương trình của bạn, như số lượng tin nhắn được xử lý hoặc phiên hoạt động, v.v.

Đây có phải là vấn đề thực sự vì thư của bạn không được xử lý trong gc ?. Hãy thử đánh dấu đồng thời và quét gc ...

* -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 
+0

Tôi khá chắc chắn đây không phải là một rò rỉ bộ nhớ vì tôi có thể thấy các gen trẻ dao động từ 100MB đến 2GB, định kỳ. Khá nhiều toàn bộ tải của obejcts mới được xóa trong chính gen trẻ. Nếu tôi đặt một kích thước heap trẻ nhỏ hơn thì tôi sẽ không thể xử lý một luồng thông điệp đột ngột. –

+0

Tôi đã thử -XX: + UseConcMarkSweepGC -XX: + UseParNewGC và sự cố chỉ trở nên tồi tệ hơn. Tôi đã xem xét phân mảnh bộ nhớ, nhưng tôi không chắc chắn làm thế nào để xác định nếu đây là nguyên nhân. –

+0

Tôi đã đọc hướng dẫn điều chỉnh gc, và nó chỉ ra rằng cả hai gc song song và thậm chí nhiều hơn để đánh dấu đồng thời và quét thực sự có nhiều khả năng gây ra phân mảnh. Vì vậy, khi nó trở nên tồi tệ hơn trong khi sử dụng concMarkSweep, nó có thể chỉ ra rằng sự phân mảnh thực sự của nó mà bạn đang thấy. Hãy thử hai lời khuyên từ hướng dẫn và xem nếu nó được tốt hơn ... "Giảm số lượng các chủ đề thu gom rác sẽ làm giảm hiệu ứng phân mảnh này như sẽ làm tăng kích thước của thế hệ đã thuê." – KarlP

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