2009-07-15 23 views
9

Trong khi theo dõi ứng dụng của chúng tôi ở Perf Mon, tôi nhận thấy% thời gian trong GC là từ 20 - 60% trong khi ứng dụng của chúng tôi đang thực hiện một quy trình chạy dài từ 30 giây đến 1,5 phút). Điều này có vẻ hơi quá mức với tôi. Điều này đặt ra hai câu hỏi quan trọng.Lý do để xem "% Time in GC" cao ở Perf Mon

  1. Tôi có khắc phục điều này quá mức không?
  2. Các tuyến đường tôi có thể thực hiện để tìm hiểu lý do tại sao rất nhiều GC đang diễn ra?
+0

Đây có phải là ASP.NET không? –

+0

Một điều cần lưu ý là bộ đếm hiệu suất này hiển thị giá trị quan sát cuối cùng, không phải là giá trị trung bình liên tục. Nó chỉ được cập nhật vào cuối mỗi chu kỳ GC. – adrianbanks

+0

Nó nằm trong một dịch vụ WCF tự lưu trữ. –

Trả lời

12

Có, điều này nghe có vẻ quá mức. Giảm số lượng GC có thể là bước duy nhất tốt nhất bạn có thể thực hiện để giảm thời gian chạy của ứng dụng của bạn (nếu đó là mục tiêu của bạn).

Một "% thời gian trong GC" cao thường do phân bổ và sau đó vứt bỏ hàng nghìn hoặc hàng triệu đối tượng. Một cách hay để tìm hiểu điều gì đang xảy ra là sử dụng một công cụ bộ nhớ hồ sơ.

Microsoft cung cấp miễn phí CLR Profiler. Điều này sẽ cho bạn thấy mọi phân bổ, nhưng sẽ làm cho ứng dụng của bạn chạy chậm hơn 10-60 lần. Bạn có thể cần phải chạy nó trên dữ liệu đầu vào ít hơn để nó có thể kết thúc phân tích trong một khoảng thời gian hợp lý.

Công cụ thương mại tuyệt vời là .NET Memory Profiler của SciTech. Điều này áp đặt chi phí thời gian chạy ít hơn nhiều và có bản dùng thử miễn phí. Bằng cách chụp nhiều ảnh trong khi quá trình của bạn đang chạy, bạn có thể tìm ra loại đối tượng nào đang được phân bổ thường xuyên (và sau đó bị phá hủy).

Khi bạn đã xác định nguồn của phân bổ, sau đó bạn cần phải kiểm tra mã và tìm ra cách phân bổ có thể được giảm. Mặc dù không có câu trả lời một kích thước phù hợp, nhưng một số điều tôi đã gặp phải trong quá khứ bao gồm:

  • String.Split có thể tạo hàng trăm chuỗi ngắn. Nếu bạn đang thực hiện rất nhiều thao tác chuỗi, nó có thể giúp xử lý chuỗi bằng cách đi theo từng ký tự.
  • Tạo mảng hoặc danh sách hàng nghìn lớp nhỏ (có kích thước dưới 24 byte) có thể tốn kém; nếu các lớp đó có thể được coi là các kiểu giá trị, nó có thể (đôi khi) cải thiện đáng kể mọi thứ để thay đổi chúng thành các cấu trúc.
  • Tạo hàng nghìn mảng nhỏ có thể tăng mức sử dụng bộ nhớ rất nhiều (vì mỗi mảng có một lượng nhỏ phí trên đầu); đôi khi chúng có thể được thay thế bằng một mảng và chỉ mục lớn thành một phần phụ của nó.
  • Có rất nhiều đối tượng cuối cùng (đặc biệt nếu chúng không được xử lý) có thể gây nhiều áp lực lên bộ thu gom rác; đảm bảo rằng bạn đang xử lý chính xác tất cả các đối tượng IDisposable, và lưu ý rằng các kiểu của riêng bạn nên (gần như) never have finalizers.
  • Microsoft có một bài viết với Garbage Collection Guidelines để cải thiện hiệu suất.
1

Lý do khác có thể là nhiều bộ sưu tập gen-1 hoặc gen-2, mỗi bộ sưu tập mất nhiều thời gian hơn và gây ra do treo trên các đối tượng lâu hơn.

Tôi đã thấy điều này xảy ra trong các ứng dụng web khi các đối tượng lỗi treo trên các đối tượng trang thực tế - buộc trang phải hoạt động miễn là các đối tượng khác đề cập đến chúng.

Phá vỡ liên kết giữa các đối tượng và trang (trong trường hợp này) khiến GC giảm xuống giá trị rất thấp. Trang web của chúng tôi hiện có hơn 100 lượt truy cập/giây và thời gian GC thường là 1% hoặc ít hơn.

2

Tôi có chính xác điều này quá mức không?

Vâng, bạn là chính xác

đường tôi có thể làm để tìm ra lý do tại sao rất nhiều GC đang xảy ra?

1. Đỗ hãy nhìn vào PerfView

PerfView là một công cụ hiệu suất phân tích giúp cô lập CPU- và vấn đề hiệu suất bộ nhớ liên quan đến.

Xem thêm: Improving Managed Code Performance

2.- Xem nếu GC.Collect hoặc GC.WaitForPendingFinalizers đang được gọi là bất cứ nơi nào trong mã của bạn hoặc thư viện của bên thứ ba. Sau này có thể gây ra việc sử dụng CPU cao.

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