Я наткнулся на очень странную проблему. Каждый раз, когда веб-приложение запускается, у dotnet.exe достаточно памяти (около 300 МБ) Однако, когда он касается некоторых частей (я чувствую, что это связано с использованием EF Core), он выделяет огромный объем памяти за короткий промежуток времени (около 8 ГБ за 2-3 секунды).
Это использование памяти занимает около 10-15 секунд, после этого память устанавливается на уровне около 600 МБ и работает нормально.
Я попробовал и dottrace, и встроенные средства диагностики, чтобы понять, что выделяет столько памяти, но не могу найти ничего значащего:
Dottrace для потока, наиболее потребляющего память, но я не смог поймать моментальный снимок памяти при очень высоком уровне (он показывает всего около 1 ГБ и около 800 МБ управляемой памяти).
VS Диагностические средства Дельта между базовой линией и сразу после увеличения памяти
Как мне узнать причину такого выделения памяти? Странно, что это не похоже на утечку, поскольку память в конечном итоге освобождается.
Вопрос: Как решить проблему выделения большого объема памяти при использовании 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
, и требуемая память сократилась примерно до половины.
Что еще более странно, это то, что диагностические инструменты показывают уменьшение памяти, не будучи непосредственно привязанным к включенному GC (см. Следующий график, GC - верхний желтый знак):
Кроме того, я дважды проверил, что я остановил все асинхронные задания (например, Кварц).