Что вызывает утечку памяти в моем Entity Framework Core dbContext? - PullRequest
0 голосов
/ 28 февраля 2020

Это касается Microsoft.EntityFrameworkCore.SqlServer, в частности версии 2.1.14

Я использую EF на своем уровне обслуживания, и один из API-интерфейсов этого сервиса предназначен для массовых операций. Весь контекстно-зависимый код использует внедрение конструктора. В строке подключения включен MARS. Я регистрирую свой контекст базы данных следующим образом:

services.AddDbContext<ServiceAvailabilityContext>(options => options.UseSqlServer(saConnection));

Я гарантировал, что весь вызывающий код запускается как выполнение задачи Scoped. У меня есть пакетный процесс, который выполняет 50 одновременных операций Task с общим количеством 500, и я попытаюсь запустить 500 регулярно. Тем не менее, со временем я заметил, что потребление памяти в Heap Size этой службой только растет и растет. У меня было до трех гигабайт с запущенным пакетным процессором и сервисом на моей машине для разработки, а также я пытался запустить сервис Runtime build. Memory Snapshot Каждая служебная команда или запрос выполняется в IMediatR IRequestHandler, и просто чтобы быть уверенным, что они были вызваны как Scoped, я добавил поведение конвейера следующим образом:

var response = await Task.Run(async () =>
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                return await next();
            }
        });

стек вызовов в основном Controller -> MediatR Request Handler (добавлен конструктор контекста) -> Operation.

Кажется, что EF просто хранит все виды коллекций в памяти и по какой-то причине не выпускает их, даже если исходный контекст вышла из области видимости, и все другие ссылки также вышли из области видимости. Я не возвращаю IQueryables, и каждый раз, когда я получаю данные, я немедленно выполняю .ToList () или .FirstorDefault (), чтобы завершить sh выключение оператора. Я никогда даже не возвращаю сам объект сущности в модели, а набираю их в виде дружественного интерфейса. Я также пытался вызвать метод для достижения точки останова и вручную вызвать G C .Collect (), который не освободил любую память!

Мой главный вопрос - просто. ... Почему? Чего мне не хватает?

1 Ответ

0 голосов
/ 05 марта 2020

Оказывается, что даже если DbContext использовался с областью действия DI, за кулисами ChangeTracker удерживает объект HashSets. Мне пришлось изменить свои операторы поиска, чтобы использовать AsNoTracking (), когда я не изменял или не отсоединял объекты, в которые я вносил изменения после вызова SaveChanges (), и это решило проблему с памятью.

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