Я наткнулся на очень странную проблему. Всякий раз, когда запускается веб-приложение, dotnet.exe имеет приличное использование памяти (около 300 МБ). Однако, когда он касается некоторых частей (я чувствую, что это связано с использованием EF Core), он выделяет огромный объем памяти за короткий промежуток времени (около 8 ГБ за 2-3 секунды).
Это использование памяти занимает около 10-15 секунд, после чего объем памяти устанавливается примерно на 600 МБ, и он работает нормально.
Я попробовал как dottrace, так и встроенные средства диагностики, чтобы понять, что выделяет столько памяти, но не нашел ничего значимого:
Dottrace для потока, потребляющего больше всего памяти, но я не смог поймать моментальный снимок памяти, будучи очень большим (он показывает мне только около ~ 1 ГБ в целом и около 800 МБ управляемой памяти).
Дельта VS Diagnostic Tools между исходным уровнем и сразу после всплеска памяти
Как я могу найти первопричину такого выделения памяти? Странно, что это не похоже на утечку, так как память со временем освобождается.
Вопрос: Как решить проблему выделения огромного объема памяти при использовании EF Core приложения ASP.NET Core 2.0?
Я думаю, что проблема действительно связана с количеством внедренных сервисов, но сначала я расскажу подробнее об архитектуре приложения. Я полагаюсь на кучу общих репозиториев, которые вводятся в доступ к данным с ограниченной областью видимости, который создает оболочку для контекста данных и помогает при необходимости сохранять множественную информацию (для различных репозиториев) в одной транзакции:
Repository<T> : IRepository<T>
<- DbContext
ScopedDataAccess : IScopedDataAccess
<- DbContext
<- logging service
<- dozens of IRepository<T>
Все "ограничено":
services.AddScoped<IScopedDataAccess, ScopedDataAccess>();
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
Я удалил около половины внедренных репозиториев в ScopedDataAccess
, и требуемая память уменьшилась примерно до половины.
Что еще более странно, средства диагностики показывают уменьшение памяти без прямой привязки к включению сборщика мусора (см. Следующий график, сборщик мусора - это верхний желтый знак):
Кроме того, я дважды проверил, что остановил все асинхронные задания (например, Quartz).