2016-10-28 12 views
5

TL; Сделано рефакторинг производительности, сайт стал медленнее. Отредактируйте анализатор параллелизма, график выглядит как lock convoys, как описано в MSDN.Блокировка конвоев на веб-сайте ASP.NET

Контекст

Я помогаю с рефакторинга веб-узлы ASP.NET для переключения пользовательских элементов управления от выполнения бизнес-логики на наборах данных для выполнения логики представления о бизнес-объектах, а также уменьшить базы данных вызовов, сделанных из пользовательских элементов управления.

Вопрос

Мы заметили существенное падение производительности (зависания/Блокировки) после внесения изменений, связанных с того, что мы думали, что будет повышение производительности в нескольких областях.

Мы используем Lean Sentry для мониторинга производительности наших веб-сайтов. Согласно диагностике зависания, в пуле потоков не было потоков и (в соответствии с описаниями на странице диагностики), когда GC работает, это останавливает создание новых потоков. По данным диагностики памяти, GC Heap и Gen 0 потребляли много памяти (~ 9 ГБ).

Что я сделал до сих пор?

  1. Я использовал профилировщика памяти в Visual Studio и определили проблемы, с нашей чрезмерной DataAdapter и DataTable использования. Потребление памяти упало до 3 ГБ, но это только помогло с блокировкой ГХ. Он все еще медленнее, чем раньше, чем мы вносили изменения, и я все еще вижу блокировку при высокой нагрузке, вызванную такими функциями, как CompilationLock.GetLock() и BuildManager.GetBuildResultFromCacheInternal(). Попутать их не принесло ничего полезного.

  2. Это сайт, на котором используется компиляция JIT. Я предположил, что проблема с CompilationLock может быть из-за компиляции JIT и хотела запустить предварительно скомпилированный сайт, но один из наших глобальных классов Utilities вызвал неоднозначность с некоторым другим классом/namespace Utilities, о котором я не знаю. Я узнал, что есть пространство имен Microsoft.Build.Utilities, но на нашем сайте оно не упоминается, и я не могу воспроизвести двусмысленность в своей собственной среде, когда я ссылаюсь на Microsoft.Build, поэтому я не мог заставить сайт работать в прекомпилированном режиме на промежуточного сервера для проверки этой теории.

  3. Я сделал дополнительные изменения в распределении памяти и количестве обращений к базе данных, используя распределение памяти и инструментальные профайлер Visual Studio в в качестве меры, но я не заметил какой-либо прогресса на производительности.

  4. Я использовал профилировщик параллелизма , чтобы собрать дополнительную информацию об использовании потоков. Я раньше не использовал этот инструмент, поэтому я не уверен в своих интерпретациях здесь. В каждом дескрипторе есть несколько потоков, и в одном ручке я вижу конкуренцию в 42%. Я вижу, что методы DataAdapter.Fill и отображаются чаще всего, когда он настроен на «Показать только мой код», а WaitForSingleObjectExImplementation отображается чаще всего, когда он настроен на «Показать весь код».

  5. я столкнулся a SO question about ASP.NET websites’ performance issues и установить EnableSessionState="ReadOnly" для каждой страницы, но я не заметил разницы с этим изменением, либо.

  6. Concurrency Visualizer и Common Patterns for Poorly-Behaved Multithreaded Applications помогли мне определить проблему. Мой график не похож на серийное исполнение, но я вижу синхронизацию 80-90%, как показано на диаграмме Lock Convoys. Я также проверил a SO question on lock convoys debugging.

Тестирование подход

Я использую Кричащие лягушки ползать на сайт для того, чтобы воспроизвести проблемы и принимая число запросов в секунду и время отклика в обоих Кричащие лягушки и Lean Sentry в качестве меры производительности , Это может быть не самый лучший способ, но разница заметна, воспроизводима, и это почти все, что у меня есть на данный момент.

Архитектура сайта

Сайт изначально был закодирован в VB.NET для .NET Framework 1.0 около 10 лет назад, и повышен до .NET Framework 4.6.1, фиксируя некоторые проблемы совместимости. До сих пор никаких архитектурных изменений не было. Существует общий класс SqlHelper, который представляет собой набор общих функций доступа к данным, таких как ExecuteDataset или ExecuteDatareader, которые возвращают либо значение DataSet, DataReader, либо String. Эти функции считывают информацию строки соединения из файла web.config и создают новые объекты SqlConnection, SqlDataAdapter, SqlDataReader и SqlCommand для выполнения операций с базой данных. Уровень доступа к данным, который использует этот общий класс, состоит из классов для каждого модуля, такого как корзина покупок, категория, продукт и т. Д., Которые должны быть созданы в каждом пользовательском элементе управления и состоят из функций, которые представляют хранимые процедуры в базе данных.

рефакторинг

Мы ввели некоторые новые объекты будут создаваться, либо внутри странице нагрузка соответствующего пользовательского элемента управления, или в OnItemDataBound случае ретрансляторах и приложенные к открытым свойствам его дочерних элементы управления пользователя, которые переработаны в используйте объект. Тем не менее, есть еще другие элементы управления дочерними пользователями, которым нужны несколько таблиц данных, поэтому мы решили сохранить одну из таблиц данных в одном из объектов и передать ее связанным пользовательским элементам управления, присвоив ее своим общедоступным свойствам.

Я предполагаю, что мы повредили производительность, представив эти объекты. Несмотря на то, что вызовы базы данных и потребление памяти кажутся сокращенными, мне интересно, все ли объекты постоянно синхронизируются.

График перед любым рефакторинга случилось:

графа после всех рефакторинга я упоминал применяться:

Вы поможете мне определить проблему?

ответ

0

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

  1. REVERT изменения в код до точки, где все или большая часть рефакторинга еще не было сделано, и когда вы имели более высокую производительность, чем что вы в настоящее время испытываете. Затем, постепенно, добавьте новые классы для повышения производительности.Если изменение не улучшает производительность, отмените его и попробуйте что-то еще.

  2. Замените некоторые из недавно добавленных классов версиями, поддерживающими интерфейсы, но не имеющих накладных расходов на производительность. Сделайте это выборочно, чтобы изолировать, где существуют проблемы с производительностью. Возможно, веб-сайт применил неизвестную ошибку производительности, которая не была вызвана предыдущими реализациями добавленных классов.

Я бы предпочел вариант 1, хотя это может показаться контрпродуктивным. Это немного похоже на футбол в США. Конечно, приятно просто спуститься по полю. Но иногда доминирующей стратегией является пунт, вернуть мяч и попытаться забить другой диск.

+0

Hi @JohnH. Благодарю за ваш ответ. Я пробовал 1-й подход с 3-мя различными версиями кода, и казалось, что больше объектов мы ввели больше запросов в секунду. Затем я попытался сохранить эти объекты в кеше, чтобы избежать запросов к базе данных, и он не показал никаких улучшений. Затем я решил, что мой подход к тестированию, просматривая запросы в секунду, не помог, так как это напрямую связано с размером страницы, которую я подтвердил, сканируя только страницы с выходным кэшем. Мы развернули код и, похоже, в лучшем состоянии, чем ожидали. – Engin

+0

Я не знаю, как я должен тестировать на этом этапе, за исключением подсчета метрик из профилировщиков. – Engin

 Смежные вопросы

  • Нет связанных вопросов^_^