Исключение OutOfMemory из BinaryFormatter.Deserialize, возникающее из его внутреннего вызова StringBuilder

У меня есть служба .NET 4 WCF, которая отправляет клиенту несколько больших объектов (~ 115 МБ), которые десериализуются клиентом. В первый раз, когда объект входит, он отлично десериализуется. Однако все последующие вызовы выдают ошибку OutOfMemoryException. Я проверил, чтобы убедиться, что все мои IDisposables заключены в using блоков. Я просмотрел другие вопросы, подобные этому, такие как десериализация исключений из памяти BinaryFormatter и Десериализация из MemoryStream вызывает исключение OutOfMemory в C#. Я пробовал некоторые решения, которые рекомендовали люди, включая использование Оптимизированный сериализатор Саймона Хьюитта. Однако, в конце концов, он по-прежнему полагается на BinaryFormatter для десериализации объектов.

Я поймал OutOfMemoryException и посмотрел на трассировку стека (см. ниже). Трассировка возникает из-за проблемы с использованием памяти в классе StringBuilder. Я читал другие статьи о том, как StringBuilder может вызвать проблемы с памятью из-за алгоритма (длина * 2), который они используют, когда требуется больше места.

at System.Text.StringBuilder.ToString()    
at System.IO.BinaryReader.ReadString()    
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectString(BinaryHeaderEnum binaryHeaderEnum)    
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()    
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)    
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)    
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)

Есть ли способ заставить BinaryFormatter работать по-другому и не использовать StringBuilder, или есть хорошая альтернатива BinaryFormatter, которая лучше управляет памятью?


person MrWuf    schedule 01.06.2012    source источник
comment
Был ли объект того же размера даже при первом вызове? Можете ли вы опубликовать код, на всякий случай..   -  person Hari Menon    schedule 01.06.2012
comment
Да, в обоих случаях был один и тот же ответ. Я каждый раз проверял точный размер байта, чтобы убедиться. Я посмотрю, смогу ли я вытащить какой-нибудь код, но он довольно длинный.   -  person MrWuf    schedule 01.06.2012


Ответы (1)


Я бы не рекомендовал использовать BinaryFormatter для чего-либо такого размера (на самом деле он, вероятно, был бы намного меньше, если бы вы не использовали двоичный форматтер). Если это довольно простые данные, такие как табличные данные, или с некоторыми ограничениями, такими как отсутствие циклических ссылок и т. д., то можно выполнить собственную двоичную сериализацию с помощью простого средства записи двоичных файлов или использовать готовый сериализатор, например protobuf-net или json .net должен быть компактнее и значительно быстрее.

person Anders Forsgren    schedule 01.06.2012