2009-03-02 32 views
13

Gặp sự cố với ứng dụng web của chúng tôi tại đây. (Asp.net 2.0 Win server 2008)Đối tượng không thu gom rác thải, nhưng không chứa gcroots

Việc sử dụng bộ nhớ của chúng tôi cho trang web, tăng trưởng và phát triển mặc dù tôi cho rằng nó vẫn ở mức khá tĩnh. (Chúng tôi có một lượng nhỏ dữ liệu được lưu trữ ở trạng thái).

Muốn tìm hiểu vấn đề là gì, tôi đã chạy System.GC.Collect(); một vài lần, lấy một bãi chứa bộ nhớ và sau đó nạp bộ nhớ này đổ vào WinDbg.

Khi tôi làm một DumpHeap -Stat tôi nhận được một số lượng lớn bất thường trên loại cụ thể treo xung quanh trong bộ nhớ.

0000064280580b40 713.471 79.908.752 PaymentOption

như vậy, làm một DumpHeap-MT cho loại hình này, tôi nhận được một chồng tài liệu tham khảo đối tượng. Chọn một số ngẫu nhiên trong số này, tôi thực hiện lệnh gcroot và lệnh quay lại báo cáo rằng không có tham chiếu nào được giữ cho nó.

Đối với tôi, đây chính xác là khi GC thu thập các mục này, nhưng vì một lý do nào đó chúng được để lại xuất sắc.

Ai có thể đưa ra giải thích về những gì có thể xảy ra không?

+0

Tôi muốn được quan tâm xem bạn đã từng giải quyết vấn đề này chưa ... – womp

+1

Thật không may là không. Chúng tôi đã giải quyết vấn đề này bằng cách tái chế quy trình khi nó đã sử dụng hơn nGB bộ nhớ để cho phép các quy trình khác. Tôi nghi ngờ đó là một vấn đề với phân mảnh và cấp phát bộ nhớ mới. Tôi sẽ sớm thực hiện một số điều tra, vì vậy tôi sẽ đăng một bản cập nhật. – Lachmania

Trả lời

1

Không có thêm thông tin nào về đơn đăng ký của bạn. Nhưng chúng tôi đã gặp phải một số vấn đề về bộ nhớ khó chịu từ lâu rồi. Bạn có sử dụng bộ nhớ đệm ASP.NET không? Như Raymond Chen thích nói, "chiến lược bộ nhớ đệm yếu là không thể tránh khỏi sự rò rỉ bộ nhớ."

Kiểm tra một công cụ khác - CLRProfiler.exe - nó sẽ giúp bạn duyệt qua cây tham chiếu đối tượng để xem đối tượng của bạn được bắt nguồn từ đâu. Điều này cũng tốt: link text

Bạn đã nghe điều này trước đây - nếu bạn phải GC.Collect, có gì đó không ổn.

+0

Không có bộ nhớ đệm, đó là điều kỳ lạ đang diễn ra ở đây. Chúng tôi có một thành phần báo cáo của bên thứ ba vì lý do nào đó sử dụng bộ nhớ cache (bạn có thể nói từ gcroots mà nó có) – Lachmania

+0

Cảm ơn mẹo trên CLRProfiler, nhưng vấn đề là khi TraverseHeap bị biến dạng và xml được viết ra, các đối tượng mà tôi quan tâm không có ở đó. (Đây là những gì tôi mong đợi, vì có vẻ như họ không có bất kỳ rễ hợp lệ nào.) – Lachmania

+0

Để rõ ràng, tôi có một nút gọi GC.Thu thập mà tôi nhấn một vài lần trước khi lấy một bãi chứa bộ nhớ, nó không nhận được cuộc gọi trong quá trình hoạt động bình thường. – Lachmania

1

Đối tượng PaymentOption được tạo trong quá trình không đồng bộ, có khả năng không? Tôi nhớ một cái gì đó về, nếu bạn không gọi EndInvoke, bạn có thể nhận được các vấn đề như thế này.

2

vài điều:

  1. GC.Collect sẽ không giúp bạn làm bất cứ gỡ lỗi. Bộ thu gom rác đã được gọi: nếu bất kỳ đối tượng nào có sẵn để thu thập thì nó đã xảy ra rồi.
  2. Bộ nhớ không hoạt động trên máy chủ bị lãng phí bộ nhớ. Bạn có chắc là bộ nhớ đang bị “rò rỉ”, hay chỉ là khung công tác quyết định nó có thể giữ nhiều thứ hơn trong việc ghi nhớ hoặc giữ nhiều bộ nhớ hơn để truy cập nhanh hơn? Trong trường hợp này tôi nghi ngờ bạn đang rò rỉ bộ nhớ, nhưng đó là một cái gì đó để kiểm tra lại.
  3. Có vẻ như điều bạn không mong đợi là giữ tham chiếu đến đối tượng PaymentOption. Có lẽ một bộ sưu tập tĩnh ở đâu đó? Hoặc tách luồng?
+1

pt2: Đồng ý bộ nhớ nhàn rỗi là lãng phí, nhưng tôi nhìn thấy biểu diễn của ram đang được sử dụng trên các đối tượng không bắt nguồn từ, nhưng dường như không được thu thập. – Lachmania

+1

pt3: Tôi nghi ngờ đó là những gì đang xảy ra, nhưng với gcroot không báo cáo bất kỳ tài liệu tham khảo, tôi không chắc chắn nơi để đi về việc tìm ra những gì có thể giữ chúng. Tôi đoán đó là điểm của câu hỏi của tôi. – Lachmania

+0

Tôi biết đây là cũ, nhưng tôi muốn thêm một cái gì đó mà xảy ra với tôi và không được đề cập bất cứ nơi nào khác trong câu hỏi. Đây có thể là đống vật thể lớn. Nếu có bất kỳ cơ hội các đối tượng này là> 80.000 byte bạn có thể có một vấn đề với điều này. –

4

Bạn có thể thử sử dụng sosex.dll trong Windbg, đây là phần mở rộng được viết để trợ giúp gỡ lỗi .NET. Có một lệnh có tên refs tương tự như gcroot, trong đó nó sẽ cho bạn thấy tất cả các đối tượng tham chiếu một đối tượng, cộng với nó sẽ hiển thị tất cả các đối tượng mà nó cũng đang tham chiếu.

Trong ví dụ trên trang web của tác giả,!refs được sử dụng đối với một đối tượng và đầu ra trông như thế này:

0:000> !refs 0000000080000db8 
Objects referenced by 0000000080000db8 (System.Threading.Mutex): 
0000000080000ef0   32 Microsoft.Win32.SafeHandles.SafeWaitHandle 

Objects referencing 0000000080000db8 (System.Threading.Mutex): 
0000000080000e08   72 System.Threading.Mutex+<>c__DisplayClass3 
0000000080000e50   64 System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode 
+0

Cảm ơn mẹo. Nhưng tôi đã kiểm tra điều này và không có tình yêu từ lệnh refs! Nó báo cáo không có rễ. grrr – Lachmania

1

Tôi đã tự điều tra cùng một vấn đề và hỏi tại sao các đối tượng không có tham chiếu nào không được thu thập.

Đối tượng lớn hơn 85.000 byte được lưu trữ trên Vùng đối tượng lớn, từ đó bộ nhớ được giải phóng ít thường xuyên hơn.

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Một PaymentOption duy nhất có thể không phải là lớn, nhưng chúng được chứa trong bộ sưu tập, hoặc chúng được dựa trên một cái gì đó giống như một DataSet? Bạn nên chọn vài trường hợp của PaymentOption/collection/DataSet và sau đó sử dụng lệnh sos! Objsize để xem chúng lớn như thế nào.

Thật không may điều này không thực sự trả lời câu hỏi. Tôi thích nghĩ rằng tôi có thể tin tưởng khuôn khổ .net để chăm sóc phát hành bộ nhớ không sử dụng bất cứ khi nào nó cần. Tuy nhiên tôi thấy rất nhiều bộ nhớ đang được sử dụng bởi quá trình công nhân đang chạy ứng dụng tôi đang xem, ngay cả khi bộ nhớ trông khá chặt chẽ trên máy chủ.

2

Trình thanh toán có triển khai trình kết thúc bằng bất kỳ cơ hội nào không? Nó có gọi là đối tượng COM STA không?

Tôi rất tò mò muốn xem kết quả của! Finalizequeue để xem số lượng đối tượng hiển thị trên heap có phải là số tiền của bất kỳ đối tượng nào có thể chờ kết thúc. Đầu ra có lẽ nên nhìn một cái gì đó như thế này:

generation 0 has 57 finalizable objects (0409b5cc->0409b6b0) 
generation 1 has 55 finalizable objects (0409b4f0->0409b5cc) 
generation 2 has 0 finalizable objects (0409b4f0->0409b4f0) 
Ready for finalization 0 objects (0409b6b0->0409b6b0) 

Nếu số lượng Sẵn sàng cho quyết toán đối tượng tiếp tục phát triển, và bộ sưu tập rác nhất định của bạn xảy ra (xác nhận qua quầy perfmon), sau đó nó có thể là một finalizer chặn chủ đề. Bạn có thể cần chụp một số ảnh chụp nhanh trong suốt quá trình xử lý (trước khi tái chế) để xác nhận. Tôi thường dựa vào số ma thuật của ba, miễn là trang web đang ở dưới một số loại tải.

Một lỗi trong trình hoàn thiện có thể chặn chuỗi trình hoàn thiện và ngăn không cho các đối tượng được thu thập.

Nếu đối tượng PaymentOption gọi đối tượng STA COM cũ, thì bài viết này ASP.NET Hang and OutOfMemory exceptions caused by STA components có thể trỏ đúng hướng.

0

FYI, SOS trong .NET 4 hỗ trợ một vài lệnh mới có thể hỗ trợ, cụ thể là !gcwhere (xác định vị trí tạo phản đối; gcgen của sosex) và !findroots (thực hiện những gì nó nói trên tin; sosex! Refs)

Cả hai đều được ghi lại trên SOS documentationmentioned on Tess Ferrandez's blog.

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