2010-04-22 35 views
5

Tình huống là tôi đang thực hiện cuộc gọi WCF đến máy chủ từ xa trả về một tài liệu XML dưới dạng chuỗi.Làm thế nào để tối đa khối tiếp giáp lớn nhất của bộ nhớ trong đối tượng lớn Heap

Hầu hết thời gian giá trị trả về này là vài K, đôi khi vài chục K, rất hiếm khi vài trăm K, nhưng rất hiếm khi nó có thể là vài megabyte (vấn đề đầu tiên là không có cách nào để tôi biết).

Đó là những dịp hiếm hoi gây đau buồn. Tôi nhận được một vết đống bắt đầu:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. 
    at System.Xml.BufferBuilder.AddBuffer() 
    at System.Xml.BufferBuilder.AppendHelper(Char* pSource, Int32 count) 
    at System.Xml.BufferBuilder.Append(Char[] value, Int32 start, Int32 count) 
    at System.Xml.XmlTextReaderImpl.ParseText() 
    at System.Xml.XmlTextReaderImpl.ParseElementContent() 
    at System.Xml.XmlTextReaderImpl.Read() 
    at System.Xml.XmlTextReader.Read() 
    at System.Xml.XmlReader.ReadElementString() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderMDRQuery.Read2_getMarketDataResponse() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer2.Deserialize(XmlSerializationReader reader) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) 
    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) 
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) 

Tôi đã đọc xung quanh và đó là vì các đối tượng lớn Heap chỉ là nhận được quá rời rạc, vì vậy ngay cả trước các cuộc gọi với một kiểm tra nhanh để StringBuilder.EnsureCapacity chỉ gây ra OutOfMemoryException được ném trước đó (và bởi vì tôi đoán ở những gì cần thiết, nó có thể không thực sự cần nhiều đến vậy kiểm tra của tôi đang gây ra nhiều vấn đề hơn là giải quyết). Một số opinions là không có nhiều tôi có thể làm về nó.

Một số trong những câu hỏi tôi đã hỏi bản thân mình:

  • Sử dụng ít bộ nhớ - có bạn kiểm tra xem có rò rỉ? Có. Việc sử dụng bộ nhớ đi lên và xuống, nhưng không có sự tăng trưởng cơ bản nào đảm bảo điều này xảy ra. Một số lần thất bại, nó đã thành công ở giai đoạn đó trước đó.
  • Chuyển một lượng nhỏ Không một lựa chọn, đây là một dịch vụ web của bên thứ ba qua mà tôi không có kiểm soát (hoặc ít nhất là nó sẽ mất nhiều thời gian để giải quyết, trong khi chờ đợi tôi vẫn có một vấn đề)
  • Bạn có thể làm điều gì đó cho LOH để làm cho nó ít có khả năng thất bại? ... bây giờ đây là khóa học hiệu quả nhất. Đó là một quá trình 32-bit (nó phải được cho các lý do chính trị, kỹ thuật và nhàm chán) nhưng thường có hàng trăm meg miễn phí (bội số của số tiền lớn nhất mà chúng tôi đã nhìn thấy thất bại).
  • Chúng tôi có thể giám sát LOH không? Sử dụng perfmon Tôi có thể theo dõi kích thước của heaps, nhưng tôi không nghĩ rằng có một cách để theo dõi khối tiếp giáp có sẵn lớn nhất của bộ nhớ.

Câu hỏi là: bất kỳ lời khuyên hoặc đề xuất nào để thử?

Trả lời

5

Bạn có thể xem lại TransferMode tài sản của ràng buộc của bạn để xem nếu bạn đáp ứng các yêu cầu để thay đổi nó từ giá trị mặc định của nó "Buffered", để "Đã phát" hoặc "StreamedResponse".

Ngoài ra, hãy xem lại các giá trị cho maxBufferPoolSizemaxBufferSize. Tăng kích thước của bộ đệm trong được sử dụng có thể giúp sử dụng bộ nhớ, đặc biệt là khi xử lý các thư lớn.

maxReceivedMessageSize cũng có thể đã được đặt nếu bạn nhận được thư lớn, nhưng tôi cũng sẽ xem lại giá trị đó.

Tôi đã thấy một trong các giá trị ở trên, nếu vượt quá ngưỡng của bạn, không kèm theo thông báo liên quan đến bộ nhớ tối nghĩa. Ngoại lệ ban đầu thực sự bị ẩn bởi thông điệp được hiển thị trên ứng dụng của tôi.Bật Truy tìm WCF đã giúp chẩn đoán sự cố và xem lỗi thực - tôi cần tăng giá trị của một hoặc nhiều thuộc tính ràng buộc ở trên.

Tôi không nhận được cảm giác về việc ràng buộc việc bạn sử dụng từ bài đăng của mình, nhưng tôi tin rằng các cài đặt này phổ biến trên các cài đặt chính. Kiểm tra tài liệu MSDN trên basicHttpBinding ví dụ.

Nếu nó thực sự là phân mảnh LOH thì không có gì phải làm về nó sau khi các nỗ lực điều chỉnh đã hết. Có thể cần phải tái chế ứng dụng này để giảm thiểu nó (tôi ghét đề xuất điều đó) nhưng nếu bạn đã cạn kiệt những nỗ lực khác, bạn có thể bị bỏ lại với điều đó.

+0

Thay đổi ràng buộc là một ý tưởng hay - Tôi sẽ thử. Tái chế luân phiên là phương sách cuối cùng của chúng tôi ... – Unsliced

+0

Chúng tôi đã may mắn được giảm thiểu bất kỳ vấn đề nào với việc xử lý tài liệu lớn thông qua các cải tiến mã (chúng tôi sở hữu cả hai điểm kết thúc) hoặc thay đổi ràng buộc, ít nhất là đến một chu kỳ bảo trì định kỳ thường xuyên (do bản vá, bản phát hành tính năng, v.v.). @ Ý tưởng của Steven về sử dụng windbg để phân tích heap cũng có thể mang lại lợi ích. Hãy thử http://blogs.msdn.com/tess/ và bạn sẽ tìm thấy thông tin tốt từ Tess Ferrandez về cách bắt đầu tại đây. Phòng thí nghiệm xuất sắc! Chúc bạn may mắn! –

1

Tôi nghĩ vấn đề của bạn Might được một Leak hội gây ra bằng cách sử dụng XmlSerializer và không sử dụng một trong hai nhà xây dựng như đã nêu trong này MSDN article:

Để tăng hiệu suất, XML serialization cơ sở hạ tầng động tạo ra hội đồng để tuần tự hóa và deserialize được chỉ định loại. Cơ sở hạ tầng tìm thấy và sử dụng lại các hội đồng đó. Hành vi này chỉ xảy ra khi sử dụng nhà xây dựng sau đây:

XmlSerializer.XmlSerializer (Type)

XmlSerializer.XmlSerializer (Type, String)

Nếu bạn sử dụng bất kỳ thầu khác, nhiều các phiên bản của cùng một lắp ráp được tạo ra và không bao giờ dỡ, dẫn đến rò rỉ bộ nhớ và hiệu suất kém.

Tốt, huh. Câu trả lời là để cache XmlSerializer của bạn (giả sử bạn thậm chí tạo nó).

Để thực sự tìm ra, bạn cần phải làm những gì Tess yêu cầu bạn thực hiện. Cô ấy là một thiên tài kỳ quái.

1

Nếu có thể tôi sẽ đi theo phương pháp tiếp cận dựa trên luồng và chỉ sử dụng bộ phân tích cú pháp Xml chuyển tiếp kết hợp, điều này cũng sẽ mang lại hiệu suất tốt hơn cho bạn.

Nếu bạn không hoàn toàn phải sử dụng WCF, bạn có thể viết HttpRequest của riêng bạn và sau đó chuyển trả lời cho XmlDeserializer và sau đó phân tích phản hồi như thế. Nó có thể cung cấp cho bạn kiểm soát nhiều hơn và cái nhìn sâu sắc vào nơi mà vấn đề thực sự xảy ra. Bạn cũng có thể thử nghiệm với một dịch vụ giả lập trả lại các tài liệu rất lớn về loại bạn đang tìm kiếm. Chúng tôi đã có rất nhiều đau đầu với sự phân mảnh LOH vì vậy tôi thực sự cảm thấy nỗi đau của bạn. Một vấn đề tôi nhận thấy khi xây dựng bộ đệm .NET có xu hướng tăng gấp đôi dung lượng mỗi khi bộ đệm được lấp đầy, gây ra phân mảnh bộ nhớ vì tài liệu có kích thước 10mb, bộ nhớ cần được cấp phát theo nhiều bước. Nếu bạn biết trước kích thước bộ đệm cần thiết, nó là hiệu quả hơn để phân bổ nó cùng một lúc. Vì vậy, nếu bạn biết tài liệu đến sẽ lớn như thế nào, bạn có thể tạo một StringBuilder với kích thước chính xác đó.

2

Tôi không thể giải quyết bất kỳ vấn đề cụ thể nào của WCF, nhưng nếu bạn cần tối đa hóa không gian LOH cho quy trình 32 bit, bạn nên tạo ứng dụng large address aware và chạy trên 64 bit. Một địa chỉ lớn nhận biết quy trình 32 bit sẽ có thể giải quyết toàn bộ không gian địa chỉ 4 GB khi chạy trên Windows 64 bit. Điều này sẽ cung cấp cho bạn một đoạn khá lớn của bộ nhớ trên không gian địa chỉ thường được sử dụng bởi quá trình này.

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