Утечка памяти asp.net mvc

Предыстория: проект Asp.net (VB.Net) с использованием IoC Ninject 2.2.0.0, шаблона репозитория и сервисного уровня.

Привязки Ninject используют InRequestScope()

Проблема. Проект вот-вот будет запущен, но стресс-тестирование показало, что сайт использует память с высокой скоростью и не освобождает ее после использования. Чтобы дать представление об этом: использование памяти около 70–100 МБ на экземпляр пользователя для каждого бизнес-процесса примерно за 2 минуты, поэтому 16 смоделированных пользователей смогли вызвать перегрузку памяти (и ЦП) и сбой сайта менее чем за 10 минут. (Сервер имеет 8 ГБ ОЗУ и на нем не запущены другие важные процессы).

Пробовали следующие решения: Попытались реализовать блоки Using с Dispose в BaseController (унаследованном всеми контроллерами), в базовом репозитории и в контексте основной базы данных.

Сайт не мог быть загружен из-за немедленного удаления dbcontext, поэтому пришлось удалить его из dispose.

Использование профилировщика памяти ANTS на самом деле не помогло, но профилировщик производительности ANTS показал, что Ninject не смог получить доступ к функции Dispose. Он пытался найти DisposableObject.cs в папке C:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Infrastructure\Disposal. Не смог найти его там, поэтому разбился. ANTS Reflector декомпилировал тот же код DisposableObject из Ninject.dll, поэтому не знаю, почему он искал его в несуществующем каталоге по умолчанию.

Поэтому попытался обновить Ninject с 2.2.0.0. на v3 с использованием Nuget PM> Install-Package Ninject.MVC3 После нескольких изменений он заработал, но теперь я застрял на ActionFilterAttribute, который был в версии 2.2.0.0, получая привязки ядра с помощью NinjectFactoryController следующим образом:

Private _mailService As IEmailService

_mailService = New StandardKernel(New NinjectControllerFactory.QuickQuoteServices()).Get(Of IEmailService)()

Теперь для Ninject.MVC3 NinjectFactoryController был закомментирован, и все привязки теперь находятся в сервисной части регистрации NinjectWebCommon.vb в папке App_Start (код VB, полученный из второго блока кода на странице https://gist.github.com/923618).

Поэтому пришлось изменить код ActionFilterAttribute на:

<Inject()>
Private _mailService As IEmailService

(строка NinjectFactoryController закомментирована).

Это возвращает _mailService как Nothing, поэтому привязка не работает.

Хотя в профилировщике памяти ANTS с использованием этой новой версии Ninject.MVC3 не наблюдалось улучшения памяти.

Профилировщик производительности ANTS работает без сбоев, но, похоже, все еще ищет другие файлы в неправильном месте (например, KernelBase.cs, ExtensionsForIEnumerableOfT.cs, Binding.cs и т. д., все они выдают ошибки, указывающие на то, что исходный код не был найден для этого файла при поиске). в папке c:\Projects\Ninject\ninject\src\Ninject...).

Мы до сих пор не можем добраться до источника утечки/перегрузки памяти, но очевидно, что пул приложений накапливает от 70 до 100 МБ данных при каждом запуске части бизнес-логики, а затем эта память не освобождается. до 20 минут полного бездействия сайта (на основе ISS 7 Idle-Timeout), что совершенно бесполезно, поскольку сайт падает задолго до того, как этот этап когда-либо будет достигнут.

Любой совет будет принят во внимание.

С уважением,

  • Абрар

Редактировать:

Наконец-то удалось заставить Ninject 3.0 работать с некоторыми указаниями.

Кроме того, проблема с использованием Ninject 3 в ActionFilterAttribute была решена с помощью объявления свойства следующим образом:

<Inject()>
    Public Property _mailService() As IEmailService
        Private Get
            Return m_mailService
        End Get
        Set(value As IEmailService)
            m_mailService = value
        End Set
    End Property
    Private m_mailService As IEmailService

Теперь, когда Ninject 3 делает свое дело, проблема с памятью немного улучшилась (т. е. память высвобождается немного больше, чем раньше), но теперь возникла новая проблема. Загрузка процессора очень высока. Эта проблема существовала еще до того, как Ninject был обновлен с 2.2 до 3.0, но обновление, похоже, не оказало на нее никакого влияния. Процессор по-прежнему загружен только с 2-3 пользователями, и это делает сайт невосприимчивым, и он, наконец, падает в течение примерно 10 минут использования.

Любые мысли будут оценены.

С уважением,

  • АбрарХФ

person AbrarHF    schedule 03.08.2012    source источник
comment
ANTS Profiler ищет исходный код NInject в этом каталоге, потому что именно там NInject .pdb говорит искать (откуда он был построен). Вы можете загрузить исходный код и перейти к нему с параметрами, которые предоставляет вам ANTS, попробовать снова декомпилировать ANTS или попытаться воссоздать .pdb с помощью Reflector.   -  person Dene B    schedule 06.08.2012
comment
Привет, Дене. Немного лучше взял ситуацию под контроль, удалив файл .pdb. В любом случае кажется, что это был отвлекающий маневр, поскольку сам Profiler работает независимо. Спасибо за руководство.   -  person AbrarHF    schedule 07.08.2012
comment
Вопрос отредактирован: Получил Ninject 3.0 для работы и улучшил память, но теперь процессор работает на пределе, что приводит к сбою сайта.   -  person AbrarHF    schedule 07.08.2012
comment
Тот факт, что вы создаете новый StandardKernel только для того, чтобы получить экземпляр службы, заставляет меня поверить, что вы неправильно используете Ninject. В классе NinjectMVC3 должно быть ровно одно ядро ​​New StandardKernel.   -  person Remo Gloor    schedule 07.08.2012
comment
Привет Ремо. Правильно, имеет смысл иметь единую сингулярную точку создания ядра. Первоначально в Ninject 2.2.0.0 ядро ​​создавалось в NinjectControllerFactory, поэтому его, вероятно, нужно было повторно создать в атрибуте ActionFilterAttribute. Это было то, что поставило меня в тупик после того, как я обновился до Ninject 3.0. Теперь у меня есть только одно новое стандартное ядро, созданное в NinjectWebCommon.vb в функции CreateKernel, а ActionFilterAttribute использует оформление ‹Inject()› только для соответствующих свойств. Теперь это, кажется, работает. Спасибо за ваше руководство.   -  person AbrarHF    schedule 07.08.2012
comment
@Remo: Кроме того, не могли бы вы предложить что-нибудь для нашей проблемы с перегрузкой процессора? Я не думаю, что это связано с самим Ninject, но эта проблема (упомянутая в отредактированной части вопроса) присутствовала, когда решение было на Ninject 2.2.0.0, и она все еще присутствует после обновления Ninject 3.0. Не могу понять, почему он может максимально использовать ЦП, поскольку мы просмотрели код, и, похоже, не требуется много тяжелой обработки. Математические вычисления очень просты, и большинство наших запросов Linq были заменены циклами For Each, поскольку они должны быть более эффективными.   -  person AbrarHF    schedule 07.08.2012
comment
@AbrarHF Вы можете использовать ANTS, чтобы понять это.   -  person Remo Gloor    schedule 07.08.2012
comment
@Remo: я попробую профилировщик производительности ANTS и посмотрю, даст ли он мне преимущество. Спасибо.   -  person AbrarHF    schedule 07.08.2012
comment
@AbrarHF Я преобразовал свой первоначальный комментарий в ответ, чтобы этот вопрос больше не оставался без ответа.   -  person Remo Gloor    schedule 10.08.2012


Ответы (1)


Тот факт, что вы создаете новый StandardKernel только для того, чтобы получить экземпляр службы, заставляет меня поверить, что вы неправильно используете Ninject.

В классе NinjectMVC3 должно быть ровно одно ядро ​​New StandardKernel.

person Remo Gloor    schedule 10.08.2012