2013-03-29 13 views
5

Trong một cuộc phỏng vấn, Tôi đã được yêu cầu đưa ra một cách để đảm bảo một khối mã trong C# có thể chạy trong thời gian nhất quán để đáp ứng một yêu cầu thời gian giả định. Người phỏng vấn đã đề cập rằng một cách là gọi trình thu gom rác để thu thập trước khi khối mã được thực thi sao cho nó giảm đáng kể xác suất của GC chạy lại trong khối mã đó. Nó được áp dụng cho các phép đo dựa trên thời gian chính xác của một thiết bị y tế, nơi thu gom rác thải có thể ảnh hưởng đến các phép đo đó.Buộc GC.Collect() để giảm cơ hội chạy trong thời gian mã nhạy cảm?

Điều đó hợp lý với tôi, nhưng tôi không thể tìm thấy bất kỳ thông tin nào được sao lưu. Sự đồng thuận chung mà tôi đã xem xét là không bao giờ gọi GC.Collect() và các trường hợp ngoại lệ không bao gồm trường hợp này.

Có thể chạy GC.Collect() thực sự làm giảm khả năng hoạt động của nó sớm không? Đây có phải là cách tiếp cận đúng để làm điều này bằng cách sử dụng khuôn khổ .net? GC.Collect() có thu thập các chương trình CLR khác không hay chỉ áp dụng cho quy trình hiện tại?

+1

Cho rằng GC chạy vào những thời điểm không xác định, tôi sẽ rất thận trọng ở bất cứ ai gọi nó và suy nghĩ nó sẽ không chạy lại trong phần mã quan trọng của họ. –

+0

Tôi đã chỉnh sửa tiêu đề của bạn. Vui lòng xem, "[Câu hỏi có nên bao gồm" thẻ "trong tiêu đề của họ không?] (Http://meta.stackexchange.com/questions/19190/)", trong đó sự đồng thuận là "không, họ không nên". –

+7

Tôi sẽ không muốn tính chính xác của phần mềm thiết bị y tế của tôi dựa vào các thay đổi của thuật toán lập lịch GC. Các tác giả của thuật toán lập lịch trình đó và các tác giả của mã thiết bị không nói chuyện với nhau. –

Trả lời

13

Câu trả lời của Jared dĩ nhiên là tuyệt vời. Để thêm một vài điểm khác:

Có thể chạy GC.Collect() thực sự làm giảm khả năng xảy ra sớm không?

Có.

Đây có phải là phương pháp phù hợp để thực hiện việc này bằng khung .net không?

tôi sẽ không muốn tính chính xác của phần mềm có chức năng do con người sống an toàn quan trọng phụ thuộc vào probabalistic đoán về không có giấy tờ hành vi của các nhà sưu tập.

Điều đó cho biết: bạn nên thực hiện WaitForPendingFinalizers sau khi bộ sưu tập. Hãy nhớ rằng, finalizers chạy trên thread của riêng mình, và đó có thể là chiếm thời gian xử lý.

GC.Collect() có thu thập các chương trình CLR khác không hay chỉ áp dụng cho quy trình hiện tại?

Thu thập bộ nhớ được quản lý trong quá trình hiện tại, vì vậy nếu bạn có nhiều tên miền ứng dụng trong một quá trình, việc thu thập trong một miền ứng dụng sẽ thu thập trong các quy trình khác. Nó không đi qua quá trình.

+1

Bạn cũng có thể đặt GCSettings.LatencyMode thành GCLatencyMode.LowLatency hoặc GCLatencyMode.SustainedLowLatency để chặn các bộ sưu tập - chỉ cần chắc chắn rằng bạn không hết bộ nhớ. http://msdn.microsoft.com/en-us/library/bb384202.aspx – ChimeraObscura

12

Chắc chắn là có thể chạy GC.Collect sẽ giảm xác suất xảy ra trong mã ngay sau đó. Có rất nhiều kịch bản dứt khoát bạn có thể vẽ theo đó nó sẽ có hành vi chính xác này. Ví dụ, nếu phân bổ tiếp theo sẽ gây ra một thu thập và GC.Collect giải phóng ít nhất số lượng bộ nhớ được cấp phát trong kịch bản.

Tuy nhiên, đó là điều tôi sẽ không bao giờ dựa vào sự thật. Có hoàn toàn không có đảm bảo rằng đây sẽ là trường hợp. Trong thực tế có thể là bộ sưu tập sẽ không xảy ra trong suốt kịch bản và thời gian để chạy buộc GC.Collect có thể vượt quá thời gian của kịch bản.

Cách duy nhất để đảm bảo rằng GC.Collect sẽ không chạy trong một kịch bản nhất định là để

  1. Không phân bổ bất kỳ bộ nhớ
  2. Đừng để bất cứ ai khác gọi GC.Collect

Rất khó để đảm bảo.

0

những gì bạn có thể có thể làm, là chỉ định để vô hiệu hóa đồng thời/nền thu gom rác thải thông qua app.config: Concurrent Garbage Collection on MSDN

+2

Điều đó sẽ giúp ích như thế nào? – svick

+0

nó sẽ vô hiệu hóa chạy GC.collect trên một chủ đề nền, vì vậy ông có thể kiểm soát những gì xảy ra khi mã quan trọng chạy – Alex

+0

Nhưng nó không làm bất cứ điều gì để ngăn chặn GC chạy trên thread hiện tại. – svick