Как справиться с огромным объемом выделяемой памяти при использовании приложения EF Core приложения ASP.NET Core 2.0? - PullRequest
4 голосов
/ 03 апреля 2019

Я наткнулся на очень странную проблему. Каждый раз, когда веб-приложение запускается, у dotnet.exe достаточно памяти (около 300 МБ) Однако, когда он касается некоторых частей (я чувствую, что это связано с использованием EF Core), он выделяет огромный объем памяти за короткий промежуток времени (около 8 ГБ за 2-3 секунды).

Это использование памяти занимает около 10-15 секунд, после этого память устанавливается на уровне около 600 МБ и работает нормально.

Я попробовал и dottrace, и встроенные средства диагностики, чтобы понять, что выделяет столько памяти, но не могу найти ничего значащего:

Dottrace для потока, наиболее потребляющего память, но я не смог поймать моментальный снимок памяти при очень высоком уровне (он показывает всего около 1 ГБ и около 800 МБ управляемой памяти).

dottrace memory usage

VS Диагностические средства Дельта между базовой линией и сразу после увеличения памяти

Visual Studio delta

Details for the most allocated type

Как мне узнать причину такого выделения памяти? Странно, что это не похоже на утечку, поскольку память в конечном итоге освобождается.

Вопрос: Как решить проблему выделения большого объема памяти при использовании 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 - верхний желтый знак):

Diagnostic tools graph

Кроме того, я дважды проверил, что я остановил все асинхронные задания (например, Кварц).

1 Ответ

0 голосов
/ 22 апреля 2019

Не полный ответ, но я сделал следующее и значительно уменьшил объем памяти (и использование ЦП):

  • Упрощенный граф зависимостей за счет разделения крупных сервисов, требующих большого количества внедренных сервисов
  • обновлен до ASP.NET Core 2.1

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

VS 2017 Diagnostic Tools snapshot

...