2010-04-22 2 views
5

Ситуация заключается в том, что я делаю вызов WCF на удаленный сервер, который возвращает XML-документ в виде строки.Как увеличить максимальный непрерывный блок памяти в кучке большого объекта

В большинстве случаев это возвращаемое значение составляет несколько K, иногда несколько десятков K, иногда несколько сотен K, но очень редко это может быть несколько мегабайт (первая проблема заключается в том, что мне неизвестно).

Это такие редкие случаи, которые вызывают горе. Я получаю трассировку стека, который начинается:

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) 

Я читал вокруг, и это происходит потому, что большой объект кучного только становится слишком фрагментированным, поэтому даже предшествующий вызов с быстрой проверки на StringBuilder.EnsureCapacity только приводит к тому, OutOfMemoryException, которое будет выбрано ранее (и потому, что я догадываюсь о том, что нужно, на самом деле это может не понадобиться, поэтому мой чек вызывает больше проблем, чем он решает). Некоторые opinions - это то, что я не могу с этим поделать.

Некоторые из вопросов, который я задал себе вопрос:

  • Использование меньше памяти - вы проверили на герметичность? Да. Использование памяти идет вверх и вниз, но нет фундаментального роста, который гарантирует, что это произойдет. Некоторое время, когда он терпит неудачу, ему это удалось на этом этапе.
  • передачи меньшего количества Не вариант, это третья сторона веб-службы, по которой я не имею никакого контроля (или, по крайней мере, это заняло бы много времени, чтобы решить, в то же время я до сих пор есть проблемы)
  • Можете ли вы что-то сделать для LOH, чтобы сделать его менее вероятным? ... сейчас это самый плодотворный курс. Это 32-битный процесс (это должно быть по различным политическим, техническим и скучным причинам), но, как правило, сотни мегабайт (кратные наибольшей сумме, за которые мы видели сбои).
  • Можем ли мы контролировать LOH? Использование perfmon Я могу отслеживать размер кучи, но я не думаю, что есть способ контролировать самый большой доступный непрерывный блок памяти.

Вопрос: любые советы или предложения по поводу вещей, чтобы попробовать?

ответ

5

Вы можете просмотреть TransferMode свойство вашего связывания, чтобы увидеть, если вы соответствуете требованиям, чтобы изменить его из значения «Buffered» по умолчанию, чтобы «текшего» или «StreamedResponse».

Кроме того, обзор значения maxBufferPoolSize и MaxBufferSize. Увеличение размера используемых внутренних буферов может помочь в использовании памяти, особенно при обработке больших сообщений.

maxReceivedMessageSize также, вероятно, уже установлен, если вы получаете большие сообщения, но я бы рассмотрел это значение.

Я видел одно из приведенных выше значений, если превышение порога, с ошибкой, связано с сообщением, связанным с памятью. Исходное исключение было фактически скрыто сообщением, которое появилось в моем приложении.Включение Трассировка WCF помогла диагностировать проблему и увидеть реальную ошибку - мне нужно было увеличить значение одного или более свойств привязки выше.

Я не понял, как вы связываете свое использование со своего поста, но я считаю, что эти настройки распространены среди основных. Посмотрите, например, документацию MSDN на странице basicHttpBinding.

Если это действительно фрагментация LOH, ничего не нужно делать по этому поводу после того, как усилия по настройке исчерпаны. Может потребоваться перезапуск приложения для смягчения (я ненавижу рекомендовать это), но если вы исчерпали другие усилия, вы можете остаться с этим.

+0

Изменение привязки - хорошая идея - я попробую. Революционный прокат был нашим последним курортом ... – Unsliced

+0

Нам посчастливилось смягчить любые проблемы с большой обработкой документов с помощью либо улучшения кода (у нас есть оба конечных пункта), либо изменения привязки, по крайней мере, чтобы пройти нас к регулярному обновлению технического обслуживания (из-за исправления, выпуска функций и т. д.). @ Идея Стивена использовать windbg для анализа кучи также может принести пользу. Попробуйте http://blogs.msdn.com/tess/, и вы найдете хорошую информацию от Тесс Феррандес о том, как начать работу здесь. Отличные лаборатории! Удачи! –

1

Я думаю, ваша проблема Может быть Ассамблея Leak, вызванные использованием XmlSerializer, а не с помощью одного из двух конструкторов, как указано в этом MSDN article:

Для повышения производительности, то XML сериализации инфраструктура динамически генерирует сборок до сериализуются и десериализуются указанные типы . Обнаружена инфраструктура, и повторно использует эти сборки. Такое поведение происходит только при использовании следующих конструктора:

XmlSerializer.XmlSerializer (тип)

XmlSerializer.XmlSerializer (Тип, String)

Если вы используете какие-либо из других конструкторов, многократные версии сгенерированы и никогда не выгружено, , что приводит к ошибке утечки и низкой производительности. .

Ницца, да. Ответ заключается в кэшировании вашего XmlSerializer (при условии, что вы его даже создадите).

Чтобы действительно понять это, вам нужно сделать то, что вам нужно сделать, Tess. Она гениальный гений.

1

Если возможно, я хотел бы использовать подход, основанный на потоке, и использовать только комбинированный синтаксический анализатор Xml в комбинации, что также даст вам лучшую производительность.

Если вам не нужно использовать WCF, вы можете написать свой собственный HttpRequest, а затем передать ответ XmlDeserializer и затем проанализировать ответ вроде этого. Это может дать вам больше контроля и понимания того, где проблема на самом деле происходит. Вы также можете поэкспериментировать с макетной службой, которая возвращает очень большие документы того типа, который вы ищете. У нас было много головных болей с фрагментацией LOH, поэтому я действительно чувствую вашу боль.

Проблема, которую я заметил при построении буферов, имеет тенденцию удваивать емкость каждый раз при заполнении буфера, что вызывает фрагментацию памяти, поскольку для документа размером 10 Мб необходимо выделить память на многие этапы. Если вы заранее знаете необходимый размер буфера, более эффективно распределить его сразу. Поэтому, если вы знаете, насколько большой будет входящий документ, вы можете создать StringBuilder с таким размером.

2

Я не могу решить какие-либо проблемы, связанные с WCF, но если вам нужно увеличить пространство LOH для 32-битного процесса, вы должны сделать приложение large address aware и запустить его на 64 бит. 32-разрядный процесс с большим адресом, способный адресовать все 4 ГБ адресного пространства при работе на 64-битной Windows. Это даст вам значительную часть памяти выше адресного пространства, обычно используемого процессом.

Смежные вопросы