Иногда наши клиенты наблюдают исключение из памяти в нашем приложении. Поскольку мы регистрируем их действия, мы можем грубо воспроизвести то, что они сделали, но если я это сделаю и профилирую приложение с помощью dotMemory, я не могу воспроизвести исключение, а используемая память (около 100 МБ управляемых + 500 МБ неуправляемых) намного меньше предела (2 ГБ, поскольку это 32-битное приложение). Кроме того, в момент, когда исключение поймано, текущее использование памяти запрашивается с помощью Process.GetCurrentProcess(). WorkSet64, который указывает на использование памяти между 500 и 900 МБ. Я знаю, что это число не очень надежное, но это еще один признак того, что должно быть достаточно памяти.исключение из памяти, хотя доступно достаточное количество памяти
Соответствующим свойством приложения является то, что он относится к временным рядам измерений (пары DateTime и double хранятся в массиве). Эти объекты могут быть достаточно большими для хранения в большой куче объекта (LOH). Таким образом, фрагментация кучи действительно имеет место, но при профилировании это делало не, похоже, большое дело. Размер LOH составлял менее 100 МБ , включая отверстия.
Возможно ли, что сборщик мусора (GC) вызывается после исключения исключения из памяти? Я думаю, что в случае неудовлетворенного запроса на выделение памяти исключение генерируется только в том случае, если GC не может собрать достаточное количество памяти. Но, возможно, это отличается от памяти, выделенной в LOH, по сравнению с памятью, выделенной в куче генерации 0?
У кого-нибудь есть идея, как мы могли бы решить эту проблему?
Мы используем VS 2010 SP1 и .NET 4.0. Вопрос может быть связан с поднятым вопросом here, here и here, но я не нашел удовлетворительного ответа там.
Обновление: Добавлен образцовый трассировки стека и график кучи fragementation
Там не единственное место, где из-за нехватки памяти исключения срабатывают, но так как это было предложено, добавить STRACK след :
Exception of type 'System.OutOfMemoryException' was thrown.
mscorlib
at System.Runtime.Serialization.ObjectIDGenerator.Rehash()
at System.Runtime.Serialization.ObjectIDGenerator.GetId(Object obj, Boolean& firstTime)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.InternalGetId(Object obj, Boolean assignUniqueIdToValueType, Type type, Boolean& isNew)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Schedule(Object obj, Boolean assignUniqueIdToValueType, Type type, WriteObjectInfo objectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, Object memberData, WriteObjectInfo objectInfo, NameInfo typeNameInfo, WriteObjectInfo memberObjectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String memberName, Type memberType, Object memberData, WriteObjectInfo memberObjectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String[] memberNames, Type[] memberTypes, Object[] memberData, WriteObjectInfo[] memberObjectInfos)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
... <methods from our application follow>
следующая диаграмма из dotMemory изображает фрагментации LOH после работы в течение около часа с инструментом:
@ ThomasAndreèLian - вы связали их с вопросом, что происходит с .NET 1.1 до установки пакета обновления 1 применяется к нему. Поскольку в их заявлении говорится, что они используют .NET 4.0, и любой .NET predating 3.5 не поддерживается, вы думаете, что это вероятно? –
@ Damien_The_Unbeliever, вы совершенно правы, я должен быть медленным сегодня, только прочитав симптомы, и он подходит. –
@Damien_The_Unbeliever - Исключения не выбрасываются из любого класса System.Drawing. Они возникают во время сериализации, например, или в других местах, где запрашивается значительный объем памяти. – MarkusParker