2009-02-26 36 views
10

Có ai gặp phải tình huống trong đó ứng dụng chịu tải phân bổ bộ nhớ cao thực hiện bộ sưu tập thế hệ thứ hai sau mỗi 100 giây không?Bộ sưu tập rác mỗi 100 giây

Chúng tôi sử dụng máy chủ 64 bit có 8-16 GB bộ nhớ vật lý.

Ứng dụng có một vài GB dữ liệu được lưu trữ trong bộ nhớ cache và không thể được xóa khỏi bộ nhớ cache vì ứng dụng thực sự được ứng dụng sử dụng. Ngoài ra, nó nhận được rất nhiều yêu cầu phân bổ đối tượng GEN 0 trong quá trình xử lý.

Điều lạ lùng với tôi là thực tế bộ sưu tập GEN 2 đã thực hiện evey 100 giây như đồng hồ. Tôi đã nghĩ rằng nó shuld có thể dự đoán được ít hơn

+3

Nếu bạn cần sự kiểm soát này nhiều hơn GC, thì có thể bạn không nên sử dụng ngôn ngữ được quản lý như C# hoặc VB.net. Và không có bạn sẽ không thực hiện một GC tốt hơn sau đó những gì có trong .net đã. Nhiều người đã thử. Tất cả đều thất bại. = P – Tony

+0

Khi viết bộ sưu tập rác của riêng bạn, người ta có quyền tự do điều chỉnh nó theo nhu cầu chính xác của bạn. Điều này thường có thể là một vấn đề đơn giản hơn nhiều so với các nhà phát triển framework .net: viết một bộ sưu tập cho tất cả các nhu cầu. Khác với một điểm cụ thể, tôi thường đồng ý với Tony. –

Trả lời

25

Nếu bạn đang chịu tải bộ nhớ cao và sử dụng rất nhiều đối tượng, thì có: GC sẽ bận ... nếu nó đang nhấn gen-2, thì có vẻ như bạn đã có của các vật thể trung/dài treo xung quanh ...

Tôi giả định rằng việc sử dụng bộ nhớ khá ổn định? Các ở trên có thể cho biết một số loại giả rò rỉ (có thể giữ quá nhiều đối tượng thông qua các sự kiện tĩnh, vv), hoặc có thể chỉ có nghĩa là bạn có một sử dụng bộ nhớ cao!

Bạn đang sử dụng bao nhiêu bộ nhớ? Bạn có thể xem xét x64 và một tấn bộ nhớ? Ngoài ra, công tắc 3gb (x86) có thể mua thêm một vài byte không?

+0

Nhưng tại sao "thực hiện bộ sưu tập thế hệ thứ hai sau mỗi 100 giây" Điều gì làm cho thời gian của GC có thể dự đoán được? –

+1

Có thể trùng hợp với cách bạn đang sử dụng bộ nhớ - nghĩa là phải mất 100 giây để trở nên quan trọng, thực hiện GC và phát hành số tiền tương tự mỗi lần (thông thường nếu bạn đang xử lý tương tự trong một khoảng thời gian dài). Hoặc nó có thể được tích hợp vào GC. Tôi không nghĩ rằng chúng tôi sẽ biết ... –

+2

Chế độ Máy chủ GC không có bất kỳ thời gian dựa trên chẩn đoán, nó được điều chỉnh động để phản ánh tỷ lệ phân bổ của bạn và các đối tượng tồn tại. – mfawzymkh

1

Tôi giả định đây là dành cho .net.

GC thu thập khi nào nó muốn dựa trên thuật toán của nó. Bạn có thể đề nghị các nhà sưu tập rác để thu thập nhưng nó có thể không thực sự làm bất cứ điều gì.

bạn có thể sử dụng GC.Collect() để yêu cầu GC xem liệu có thể thu gom rác hay không. Tuy nhiên nó có thể không thực sự loại bỏ các mục từ bộ nhớ.

LƯU Ý: Ngoài ra, hãy đảm bảo bạn đang xóa tài liệu tham khảo chính xác. Có nghĩa là unhooking sự kiện, Xóa tài liệu tham khảo giữa các đối tượng. Điều này sẽ giúp GC trong các đối tượng được thu thập không còn trong phạm vi.

4

Để điều đó xảy ra, việc sử dụng bộ nhớ phải rất nhất quán cho cả quá trình và hệ thống. thu gom rác thải được kích hoạt bởi một trong những sự kiện này:

  • hệ ngân sách 0 là đầy đủ
  • GC.Collect() được gọi
  • CLR muốn bộ nhớ giải phóng
  • AppDomain shutdown
  • CLR shutdown

Các ứng viên có khả năng trong trường hợp của bạn có thể là tập hợp thường xuyên (nghĩa là do phân bổ) hoặc thu thập theo thời gian().

CHỈNH SỬA: Chỉ cần làm rõ về phân bổ. Phân bổ các đối tượng thường xuyên luôn luôn xảy ra trong thế hệ 0 (ngoại lệ là các đối tượng lớn 85000 byte hoặc nhiều hơn, được phân bổ trên đống đối tượng lớn). Các cá thể chỉ được chuyển đến thế hệ 1 và 2, khi chúng tồn tại một bộ sưu tập. Không có phân bổ trực tiếp trong thế hệ 1 và 2.

Ngoài ra, bộ sưu tập thế hệ 2 (còn được gọi là thu thập đầy đủ) được thực hiện khi bộ sưu tập thế hệ 0/1 không giải phóng đủ bộ nhớ (hoặc khi thu thập đầy đủ được yêu cầu rõ ràng).

+0

Chúng tôi không sử dụng GC.Collect và không tắt máy được thực hiện. – MichaelT

8

Nếu bạn đang chạy CPU lõi kép, hãy thử đặt GCServer = "true" trong app/web.config.

Trong trường hợp của tôi, nó chiếm khoảng 10% của GC ban đầu và ứng dụng cảm thấy rất nhiều snappier.

4

Có thể bạn đang tạo ra nhiều đối tượng hơn, sau đó có thể vừa với heap trẻ cùng một lúc hoặc bạn bị rò rỉ bộ nhớ.

Nếu bạn đang tạo nhiều đối tượng cần phải hoạt động cùng một lúc, thì có thể bạn đang tràn bộ phận trẻ và một số đối tượng phải được sao chép sang thế hệ cũ hơn. Điều này lực lượng bộ sưu tập đầy đủ thường xuyên hơn khi đống cũ đầy lên. Bạn có thể cần phải tìm một cách để phân bổ ít đối tượng hơn trong trường hợp này trừ khi có một cách để yêu cầu một heap trẻ lớn hơn như có với Sun JVM.

Nếu bạn thực sự lưu trữ các đối tượng ở một nơi nào đó (nói trong danh sách thuộc sở hữu của một đối tượng cũ), thì bạn sẽ bị rò rỉ hợp lý. Nói chung, bạn không muốn các đối tượng cũ đề cập đến các đối tượng trẻ. Điều này có xu hướng để có được các đối tượng trẻ được thúc đẩy và các thuật toán GC thường được tối ưu hóa cho nó không xảy ra. Ngoài ra, bạn có thể muốn xem xét việc xóa các tham chiếu nếu điều này làm giảm đáng kể phạm vi mà một đối tượng có thể còn sống (mặc dù nó thường là thừa).

Chặn điều đó và bạn chỉ có mức sử dụng bộ nhớ cao bất thường, có thể không có nhiều thứ bạn có thể làm. Hãy nhớ rằng đối với bất kỳ chương trình chạy dài nào, bạn sẽ phải thực hiện một số GCing, và càng nhiều bộ nhớ bạn cần tại một thời điểm thì càng thường xuyên.

+0

Điểm có vẻ rất kỳ quặc đối với tôi đó là sự xen kẽ 100 giây với bộ sưu tập GC được thực hiện – MichaelT

2

Tôi giả sử bạn đang sử dụng .NET. Tôi không chắc bạn đang sử dụng công cụ gì, nhưng tôi là một fan hâm mộ lớn của trình biên dịch kiến ​​của Red Gate. Tôi sử dụng nó tại nơi làm việc. Nó có thể xác định các đối tượng nào đang hogging tài nguyên. Một khi bạn thu hẹp nó xuống, hy vọng, bạn có thể tìm thấy mã vi phạm và giải phóng tài nguyên đúng cách.

Kiểm tra mã của bạn và đảm bảo bạn đang gọi Dispose() bất cứ khi nào có thể.

Hãy cho chúng tôi biết cách thực hiện.

5

Bộ sưu tập thế hệ thứ hai xảy ra như đồng hồ sẽ gợi ý rằng phương pháp GC.Collect được gọi là đồng hồ, hoặc phân bổ giống như đồng hồ.

Tính ngẫu nhiên bạn mong đợi thấy trong thu thập rác không có khả năng xảy ra trừ khi phân bổ hoặc GC.Collect cuộc gọi, thực sự là ngẫu nhiên. Cho rằng ứng dụng máy chủ của bạn đang ở mức tải cao như vậy và bạn tạo các đối tượng mới trong quá trình xử lý, tôi sẽ cân nhắc việc tái cấu trúc mã để xem có ít đối tượng có thể được tạo mới trong quá trình xử lý hay không.

Một nhóm đối tượng khác với hầu hết các bộ gom rác trong các đối tượng trong một hồ bơi có thể được sử dụng lại ngay khi chúng được đưa trở lại trong hồ bơi và bộ thu gom rác cần thực hiện bộ sưu tập trước một khối bộ nhớ trước đó. có thể được sử dụng lại như một đối tượng khác.

1

Vì bạn đang chạy trên một máy chủ, tôi giả sử nó là một máy đa lõi là tốt. Nếu đây là trường hợp, sau đó bạn nhận được Server GC hương vị theo mặc định, vì vậy bạn không cần phải đặt bất cứ điều gì trong tập tin cấu hình của bạn.

Thực tế là bạn đang thu thập bộ sưu tập Gen2 cứ sau 100 giây là một yếu tố của mẫu phân bổ và mô hình tuổi thọ đối tượng của bạn. nếu mô hình phân bổ của bạn là phù hợp, bạn sẽ nhận được phù hợp GC, bạn có thể xác minh hành vi này bằng cách nhìn dưới Memory Net CLR Perf quầy dưới perfmon

Bạn sẽ cần phải theo dõi các chỉ số sau

  1. Gen0 Bộ sưu tập

  2. Gen 1 bộ sưu tập

  3. Gen 2 bộ sưu tập

  4. Phân bổ số byte trên giây
  5. Byte trong tất cả các vùng.

bạn sẽ thấy chỉ số cuối cùng di chuyển như ghép hình, tăng, Bộ sưu tập Gen2 bắt đầu, giảm lại và chu kỳ lặp lại chính nó.

Để tránh điều này, bạn sẽ cần phải kiểm tra

  • có thể bạn có thể đối tượng giữa yêu cầu, trong hồ ?, điều này sẽ tránh GC tất cả cùng nhau.
  • Nếu không, bạn có thể giảm số lượng đối tượng bạn phân bổ cho mỗi yêu cầu không?

Hy vọng điều này sẽ hữu ích. Cảm ơn

+0

Trên nhận xét của bạn rằng chế độ máy chủ là mặc định trên môi trường đa lõi - tuyên bố đó không được tài liệu hỗ trợ: http: // msdn. microsoft.com/en-us/library/ms229357.aspx. Những trạng thái này là cài đặt luôn luôn sai, bất kể có bao nhiêu lõi trên máy. – Slaggg

0

Tôi không hiểu điều gì gây ra "bộ sưu tập thế hệ thứ hai được thực hiện cứ sau 100 giây", rất hiếm khi thấy một hệ thống thực tế hoạt động trong chu kỳ "đồng hồ".

Nếu bạn đang chịu tải bộ nhớ cao và sử dụng nhiều đối tượng, thì có: GC sẽ bận ... nếu nó đang nhấn gen-2, thì có vẻ như bạn đã có rất nhiều tiền cược/các vật thể sống lâu treo xung quanh ... Bạn có thể tạo ra nhiều vật thể hơn sau đó có thể vừa vặn trong đống trẻ cùng một lúc hoặc bạn bị rò rỉ bộ nhớ.

Giả sử bạn không bị rò rỉ, bạn đã kiểm tra với memory profiler chưa? Tôi cũng giả sử bạn không tạo ra nhiều rác không cần thiết (ví dụ: string1 + = string2 bên trong vòng lặp).

Tôi có thể nghĩ về hai điều mà có thể trợ giúp.

Bằng cách giới hạn số lượng yêu cầu (luồng) Asp.net xử lý cùng một lúc, bạn có thể giới hạn số lượng đối tượng trực tiếp và tăng tốc xử lý yêu cầu duy nhất, do đó không giữ đối tượng tồn tại lâu. (Bạn đang nhận được rất nhiều công tắc liên hệ chỉ?)

Nếu bạn đang lưu trữ đối tượng trong bộ nhớ cache Asp.net và/hoặc phiên Asp.net. Bạn có thể thử sử dụng kho lưu trữ ngoài quy trình cho thông tin lưu trữ này, ví dụ: máy chủ phiên Asp.net, máy chủ phiên bên thứ ba, memcache hoặc máy chủ bộ nhớ cache được phát hành gần đây của Microsoft (Velocity). Chỉ cần đọc lại dữ liệu từ cơ sở dữ liệu khi bạn cần, có thể tốt hơn sau đó lưu trữ nó trong đối tượng sống lâu.

Thất bại ở trên, bạn đang sử dụng bao nhiêu bộ nhớ?Bạn có thể xem xét x64 và một tấn bộ nhớ? Hoặc một webfarm.

0

Rằng người thu gom rác đang được gọi thường xuyên không phải là vấn đề lớn - nó có thể là cờ mà bạn không xử lý tốt nhất bộ nhớ của bạn. thành các phương thức).

Thu gom rác nên không xác định. Điều đó lưu ý, nếu bạn đang chạy một số nhiệm vụ quan trọng, nhưng thread của bạn (s) đang ngủ tại một số điểm (như mỗi 100 giây) nó là hợp lý mà các nhà sưu tập rác có thể mất cơ hội để thu thập tại thời điểm đó. Nhiều khả năng là mức tiêu thụ do các đỉnh phân bổ ở các khoảng thời gian thường xuyên hơn hoặc ít hơn và bộ thu gom rác được gọi để lấy bộ nhớ không sử dụng.

Tôi đặc biệt khuyên bạn nên lập cấu hình mức tiêu thụ bộ nhớ của ứng dụng của bạn.

0

Nó có thể chỉ là ứng dụng của bạn tạo ra một đối tượng khổng lồ mỗi 100, và vì vậy GC buộc phải thực hiện công việc của mình?

0

Tôi cũng đã xem tần suất 100 giây này, nó không xảy ra trên tất cả các thiết lập sản xuất, nhưng tôi đã thấy nó cục bộ và trên các thiết lập khác.

+0

Cuối cùng tôi đã giải quyết nó, dường như chúng tôi không sử dụng GC máy chủ sau khi tất cả sau khi chuyển sang máy chủ GC không có GC2 nơi được gọi. Rõ ràng GC đồng thời có giả định rằng tìm số lượng bộ nhớ được cấp phát mỗi giây và nếu nó cao hơn giá trị nào đó mà nó gọi là gen 2 GC cứ 100 giây một lần – MichaelT

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