2009-04-02 2 views
5

Сущность Framework, похоже, использует избыточную память при вставке новых объектов в базу данных.Использование памяти фреймворка Entity

for(int i = 0; i < numOwners; ++i) 
{ 
    var owner = Owner.CreateOwner(); 
    db.AddToOwnerSet(owner); 
    for(int j = 0; j < numChildren; ++j) 
    { 
     var child = Child.CreateChild(); 
     owner.Childs.Add(child); 
    } 
} 
db.SaveChanges(); 

На данный момент эти объекты содержат очень мало элементов данных. При вставке 140 000 из этих объектов в базу данных общее использование памяти приложения было 600 МБ и 1,2 гигабайта для 300 000. Эти объекты небольшие, просто имя строки и целочисленный ключ.

Я могу уменьшить использование памяти, поместив вызовы SaveChanges в цикл, но время выполнения становится намного хуже, и это уже довольно плохо.

Кто-нибудь знает, почему инфраструктура сущности использует так много памяти или как заставить ее использовать меньше памяти?

ответ

2

Поскольку структура сущности хранит данные в памяти (как и многие ORM), то, как и во многих коллекциях в памяти, возможно, есть внутренние массивы. Когда вы добавляете элементы в коллекцию, внутренний массив удваивается.

Например, если у вас есть коллекция ArrayList, содержащая 256 элементов, и добавьте к ней 257-й элемент, то, что происходит внутри, выделяется новый блок памяти для массива элементов 512, скопирован в новый массив элементов 512, а затем массив 256 элементов доступен для сбора мусора. Таким образом, в точке перехода у вас будет 768 предметов, выделенных в память только потому, что вы добавили 257-й элемент. Я столкнулся с головными болями с этим при использовании memystream, потому что вам нужно почти в 3 раза больше неотъемлемой неразмещенной памяти, чем того, что вам действительно нужно. Это свойство .Capacity, которое вы видите в коллекциях, и оно почти всегда имеет силу 2 (поскольку по мере необходимости оно удваивается).

Моя ставка заключается в наличии внутренних массивов, размер которых в два раза больше по мере необходимости для поддержки ваших коллекций объектов памяти. Таким образом, 300 000 объектов одного типа, вероятно, будут храниться во внутреннем массиве размером 524,288. Кроме того, если это похоже на аналогичные методы в другом месте .NEt Framework, то всякий раз, когда был добавлен 262145-й элемент, оба массива из 262144 и 524288 существовали в памяти, а элементы были скопированы в новый массив. В общей сложности 786432 элемента в памяти. Старый массив будет придерживаться, пока сборщик мусора не решит, что он больше не нужен.

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

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

1

Ваши объекты могут быть «маленькими» с точки зрения фактических данных, но каждый объект не является DTO - платформа Entity Framework прикрепляет множество шаблонных кодов к каждому из ваших объектов, что означает, что фактический размер каждого объекта вполне большой.

Если вы последовательно работаете с крупными объектными графами, подумайте над тем, чтобы использовать что-то вроде NHibernate, которое является стабильным, зрелым и проверенным для работы. Система Entity Framework очень сильно отстает по характеристикам и производительности.

2

Я знаю, что это старый вопрос, но сегодня я столкнулся с той же проблемой и сумел выяснить, что вызвало это!

Похоже, что генерация SQL-скриптов отвечает за большой скачок в памяти. Я обнаружил, что создание хранимых процедур и привязка их к моим объектам (но убедитесь, что вы вернули значение для идентификаторов, как показано в this article), сохранили мне более 300 мб памяти.

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