Запрос объектов из статического списка, вызывающий всплески использования процессора на сервере - PullRequest
4 голосов
/ 08 января 2012

У нас есть функция, похожая на связанные вопросы в SO, где мы показываем связанные записи при просмотре данной записи. Связанные записи извлекались путем вызова базы данных каждый раз при загрузке страницы. Чтобы уменьшить нагрузку на базу данных, я создал статический список этих записей, которые загружаю в Application_Start, и теперь использую запрос Linq для запроса этого списка.

По большей части это работает нормально. Нагрузка на БД уменьшилась, и профилировщик Sql показывает, что больше нет связанных записей запроса. Я перенес это изменение прошлой ночью, а сегодня утром обнаружил, что рабочий процесс IIS работает с CPU на 100%, а веб-сайт не отвечает. Я вернулся к старому коду (где я запрашиваю БД), и на веб-сервере все было в порядке, но нагрузка на БД возросла. Так что я снова переключился на новый код и начал изучать загрузку процессора на веб-сервере. Это то, что я заметил.

При использовании старого кода, который запрашивает базу данных, использование процессором процесса IIS Worker незначительно и изменений практически нет (прямая линия видна на вкладке производительности диспетчера задач). Однако при использовании нового кода, который создает и запрашивает статический список, я вижу всплески использования ЦП рабочим процессом IIS. В большинстве случаев это составляет от 1 до 5%, но время от времени оно резко возрастает, и максимум, который я видел, составляет 40% с тех пор, как я начал наблюдать. Мне интересно, почему это происходит и может ли это привести к сбою рабочего процесса под большой нагрузкой?

Вот часть кода, который запрашивает статический список

    if (validSearchLatLong && (usePincodeLatLong || distanceFilterLimit != distanceLimit))
        {
            filteredRecords = StaticRecords.Where(job => LatLongDistance(centerLatitude, centerLongitude, job.lat, job.lon) <= distanceFilterLimit || (!string.IsNullOrEmpty(this.PreferredJobCity) ? job.city == this.PreferredJobCity : false)).ToList();
        }
        else
        {
            filteredRecords = StaticRecords.Where(job => (this.PreferredJobCity != "" ? job.city == this.PreferredJobCity : (this.City != "" ? job.city == this.city : (state != "" ? job.state.Trim() == state.Trim() : false)))).ToList();
        }

        if (RecordsearchFilter.JobCategories.Count > 0 && RecordsearchFilter.EnableFilter)
        {
            filteredRecords = filteredRecords.Where(job => this.RecordsearchFilter.JobCategories.Contains(job.JobCategoryClass)).ToList();
        }
        else
        {
            filteredRecords = filteredRecords.Where(job => MatchJobCategories(job.JobCategory, (short)this.jobCategory.SqlId) > 0).ToList();
        }

Список поддерживает несколько одновременных считывателей, поэтому StaticRecords не должен быть фактором блокировки. И после этого я создаю FilterRecords, который представляет собой новый отфильтрованный список, который должен быть независимым от других потоков.

Каковы могут быть возможные причины скачков ЦП, и могло ли это привести к более раннему сбою рабочего процесса IIS?

============ EDIT ==============

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

Но мой вопрос все еще остается, почему всплески в процессоре?

Когда я говорю

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

я не прав?

Ответы [ 2 ]

3 голосов
/ 08 января 2012

SQL Server обычно очень эффективен при запросах, особенно если вы правильно оптимизировали индексы.

Ваш новый подход StaticRecords требует сканирования в памяти всех элементов, выполняя предикат Where для каждого. Вероятно, это является причиной увеличения загрузки процессора, особенно если в StaticRecords много элементов. Попробуйте подключить профилировщик и убедитесь сами. В целом, я ожидаю, что этот вид фильтрации будет работать на несколько порядков лучше при работе на SQL Server по сравнению с фильтрацией в памяти.

1 голос
/ 08 января 2012

Проблемы с производительностью, вероятно, из-за сканирования List в StaticRecords.

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

Что касается причины вашего сбоя и 100% пиков ЦП, я не вижу явной ошибки в опубликованном вами коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...