Использование памяти Entity Framework - PullRequest
5 голосов
/ 02 апреля 2009

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

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 в цикл, но тогда время выполнения становится намного хуже, и это уже довольно плохо.

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

Ответы [ 3 ]

2 голосов
/ 16 декабря 2010

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

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

2 голосов
/ 02 апреля 2009

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

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

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

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

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

1 голос
/ 22 апреля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...