Общие сведения о производительности

Visual Studio 2010

Обновлен: Ноябрь 2007

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

Содержание раздела:

Ниже приведены ссылки на ресурсы на веб-узле корпорации Майкрософт, содержащие общие рекомендации по повышению производительности веб-узлов ASP.NET Web.

К началу

В этом разделе рассматриваются приемы, которые можно использовать для максимизации производительности веб-приложений ASP.NET. Рекомендации делятся на следующие разделы:

Обработка серверных и страничных элементов управления

Следующие рекомендации касаются эффективных методов работы с элементами управления и страницами ASP.NET.

  • Избегайте ненужного обмена данными с сервером   В некоторых ситуациях для выполнения тех или иных задач в коде обозревателя можно использовать возможности ASP.NET AJAX и частичную отрисовку страниц, обходясь без полной обратной передачи. Например, с помощью ASP.NET AJAX можно проверять вводимые пользователем данные в обозревателе, прежде чем отправлять их на сервер. Дополнительные сведения см. в разделах Общие сведения о ASP.NET AJAX и Общие сведения о частичной отрисовке страниц.

  • В большинстве случаев при отсутствии необходимости передачи информации на сервер для проверки или записи в хранилище данных улучшить производительность страницы (а следовательно, и ощущения пользователей от работы с ней) можно путем устранения циклов передачи данных между сервером и приложением.

  • При разработке пользовательских серверных элементов управления следует рассмотреть возможность реализации некоторой их функциональности с помощью клиентского кода. Это может значительно снизить количество обращений к веб-серверу. Дополнительные сведения см. в разделах Разработка пользовательских серверных элементов управления ASP.NET и Создание пользовательского клиента сценария с помощью библиотеки Microsoft AJAX.

  • Используйте свойство IsPostBack объекта Page во избежание лишней обработки   Следует избегать выполнения кода при каждой обратной передаче в случаях, когда выполнять его на самом деле необходимо только при первом запросе страницы. Проверка свойства IsPostBack позволяет выполнять код в зависимости от того, была ли страница создана в ответ на событие серверного элемента управления.

  • Не отключайте буферизацию без необходимости   Отключение буферизации веб-страниц ASP.NET значительно снижает производительность. Дополнительные сведения см. в описании свойства Buffer.

  • Используйте метод Transfer объекта Server или межстраничную запись данных для перенаправления между страницами ASP.NET в пределах одного приложения.   Дополнительные сведения см. в разделе Перенаправление пользователей на другую страницу.

Управление состоянием

Следующие рекомендации касаются способов эффективного управления состоянием.

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

    По умолчанию состояние просмотра включено для всех серверных элементов управления. Чтобы отключить его для определенного элемента управления, установите для свойства EnableViewState элемента управления значение false, как показано в следующем примере.

    <asp:datagrid EnableViewState="false" datasource="..." 
       runat="server"/>
    

    Отключить состояние просмотра также можно для страницы, используя для этого директиву @ Page, как показано в следующем примере.

    <%@ Page EnableViewState="false" %>
    

    Это рекомендуется делать в случаях, если страница не передает данные на сервер.

    Cc668225.alert_note(ru-ru,VS.100).gifПримечание.

    Атрибут EnableViewState также поддерживается директивой @ Control, что позволяет указать, включено ли состояние просмотра для пользовательского элемента управления.

    Чтобы анализировать размер состояния просмотра для страницы, на странице необходимо включить трассировку, добавив атрибут trace="true" в директиву @ Page. В выходных данных трассировки в таблице Иерархия элементов управления см. столбец Состояние просмотра. Дополнительные сведения см. в разделе Общие сведения о трассировке ASP.NET.

  • Не шифруйте состояние просмотра без необходимости   Шифрование состояния просмотра не дает пользователям считывать значения в скрытых полях состояния просмотра формы. Например, имеет смысл шифровать состояние просмотра, если на странице присутствует элемент управления GridView с полем идентификатора в свойстве DataKeyNames для координации обновления записей. Чтобы идентификатор не был виден пользователям, состояние просмотра можно зашифровать. Однако шифрование приводит к постоянным затратам производительности при инициализации и вносит дополнительные затраты, которые зависят от размеров шифруемого состояния просмотра. Шифрование производится при каждой загрузке страницы. Следовательно, отрицательное влияние на производительность будет иметь место при первом запросе страницы и при каждой обратной передаче.

  • Отключайте состояние сеанса, когда оно не требуется   Чтобы отключить состояние сеанса на странице, установите для атрибута EnableSessionState в директиве @ Page состояние false, как показано в следующем примере.

    <%@ Page EnableSessionState="false" %>
    
    Cc668225.alert_note(ru-ru,VS.100).gifПримечание.

    Если странице требуется доступ к переменным сеанса, но не требуется их создание или изменение, для атрибута EnableSessionState в директиве @ Page устанавливается значение ReadOnly.

    Можно также отключить состояние сеанса для методов веб-служб ASP.NET. Дополнительные сведения см. в разделе Общие сведения о службах приложений ASP.NET.

    Чтобы отключить состояние сеанса для приложения, задайте для атрибута Mode значение Off в разделе SessionState файла Web.config приложения, как показано в следующем примере:

    <sessionState mode="Off" />
    
  • Выбирайте поставщик состояния сеанса, отвечающий требованиям приложения    Платформа ASP.NET предоставляет несколько способов хранения данных сеанса для приложения: внутрипроцессное состояние сеанса, внепроцессное состояние сеанса в качестве службы Windows и внепроцессное состояние сеанса в базе данных SQL Server. (Для хранения данных сеанса в выбранном хранилище данных также может создаваться пользовательский поставщик состояния сеанса.) Каждый способ обладает своими преимуществами, однако внутрипроцессное состояние сеанса является наиболее быстрым решением. Если состояние сеанса используется для хранения небольших объемов данных, рекомендуется использовать внутрипроцессный поставщик. Внепроцессные варианты хранения состояния сеанса рекомендуется использовать при масштабировании приложения на несколько процессоров или компьютеров или же в ситуациях, когда необходимо сохранять данные при перезапуске сервера или процесса. Дополнительные сведения см. в разделе Общие сведения о состоянии сеанса ASP.NET.

Доступ к данным

Следующие рекомендации описывают способы эффективного доступа к данным приложения.

  • Используйте SQL Server и хранимые процедуры для доступа к данным   При создании высокопроизводительных масштабируемых веб-приложений оптимальным вариантом для хранения данных является SQL Server. При работе с управляемым поставщиком SQL Server производительность можно дополнительно повысить путем использования скомпилированных хранимых процедур вместо команд SQL в случаях, когда это возможно. Дополнительные сведения см. в разделе Настройка параметров и типов данных параметров (ADO.NET).

  • Используйте класс SqlDataReader в качестве курсора быстрого последовательного доступа к данным   Класс SqlDataReader создает последовательный доступный только для чтения поток данных, получаемый из базы данных SQL Server. Для прямого чтения данных из точки подключения к базе данных класс SqlDataReader использует собственный сетевой формат передачи данных SQL Server. По возможности следует использовать именно класс SqlDataReader, так как он обеспечивает большую производительность, чем класс DataSet. Например, при привязке элемента управления данными к элементу управления SqlDataSource добиться большей производительности можно, установив для свойства DataSourceMode значения DataReader. (Класс считывания данных, однако, поддерживает меньше функциональных возможностей, чем режим DataSet.) Класс SqlDataReader реализует интерфейс IEnumerable, что позволяет привязывать к нему серверные элементы управления. Дополнительные сведения см. в описании класса SqlDataReader и в разделе Доступ к данным с помощью ASP.NET.

  • По возможности кэшируйте данные и вывод страниц   Если страницы или данные не требуется вычислять динамически при каждом запросе страницы, следует использовать средства кэширования ASP.NET. При возможности разрабатывайте страницы и запросы к данным с учетом возможности кэширования, в особенности на наиболее загруженных участках веб-узла. Грамотное применение кэширования может повысить производительность веб-узла больше, чем это смогут сделать любые другие функции платформы .NET Framework.

    При использовании кэширования ASP.NET полезно придерживаться следующих принципов. Во-первых, не следует кэшировать слишком много элементов, так как каждый кэшируемый элемент требует ресурсов памяти сервера. Например, не нужно кэшировать элементы, которые легко пересчитываются или редко используются. Во-вторых, не рекомендуется задавать для кэшируемых элементов короткий срок действия. Быстро удаляемые элементы могут стать источником дополнительной работы для кода очистки и сборщика мусора. Отслеживать частоту обновления кэша, связанную с окончанием срока действия элементов, можно с помощью счетчика производительности "Частота текучести данных в общем кэше", связанного с объектом производительности "Приложения ASP.NET". Частое обновление может указывать на наличие проблемы, особенно в случае удаления элементов до истечения срока их действия. (В некоторых случаях такую ситуацию называют недостатком памяти.)

    Дополнительные сведения о кэшировании выходных данных страниц и запросов к данным см. в разделе Общие сведения о кэшировании в ASP.NET.

  • Разумно используйте зависимость кэша от таблиц SQL    Для организации кэширования данных с сервера SQL Server платформа ASP.NET поддерживает как табличный опрос, так и уведомления о запросах (в зависимости от используемой версии SQL Server). Табличный опрос поддерживается всеми версиями SQL Server. При табличном опросе, если в таблице изменяются какие-либо данные, все зависимые от этой таблицы элементы кэша становятся недействительными. Это может привести к ненужному обновлению кэша. Табличный опрос не рекомендуется использовать для таблиц, в которых часто происходят изменения. Например, табличный опрос имеет смысл использовать для таблицы каталогов, в которой изменения происходят нечасто. При этом не следует использовать табличный опрос для часто обновляемой таблицы заказов.

    Уведомления о запросах поддерживаются в SQL Server 2005 и более поздних версиях. Механизм уведомления о запросах заключается в использовании SQL-запросов для обнаружения изменений в целевом наборе строк. Это снижает количество уведомлений, отправляемых при изменении таблицы. Уведомления о запросах способны обеспечить лучшую производительность, чем табличный опрос. Тем не менее, масштабировать этот механизм на тысячи запросов нельзя.

    Дополнительные сведения о зависимости кэша от таблиц SQL см. в разделах Пошаговое руководство. Использование кэширования выходных данных ASP.NET с SQL Server и Кэширование в ASP.NET с помощью класса SqlCacheDependency.

  • Используйте разбиение по страницам и сортировку в источнике данных вместо разбиения по страницам и сортировки в пользовательском интерфейсе   Функция разбиения про страницам пользовательского интерфейса таких элементов управления данными, как DetailsView и GridView, может использоваться с любым объектом источника данных, поддерживающим интерфейс ICollection. При каждой операции разбиения по страницам элемент управления данными отправляет источнику данных запрос на получение всей коллекции данных, выбирает из нее отображаемую строку или строки, а остальные данные игнорирует.

    Если элемент управления источником данных реализует класс DataSourceView, а свойство CanPage возвращает значение true, вместо разбиения по страницам в пользовательском интерфейсе элемент управления данными будет использовать разбиение по страницам в источнике данных. В этом случае элемент управления данными будет запрашивать только строки, необходимые для отображения каждой страницы. Таким образом, разбиение по страницам в источнике данных оказывается более эффективным, чем разбиение по страницам в пользовательском интерфейсе. Из стандартных элементов управления ASP.NET разбиение по страницам в источнике данных поддерживают только элементы управления источником данных ObjectDataSource и LinqDataSource. Для включения функции разбиения по страницам в источнике данных в других элементах управления источником данных необходимо наследование от соответствующего элемента управления источника данных с последующей модификацией его поведения.

  • Используйте столбец временных меток для управления параллелизмом с помощью элемента управления LinqDataSource   Если база данных SQL Server не содержит столбец Timestamp (тип данных SQL Server), элемент управления LinqDataSource проверяет параллелизм данных, сохраняя исходные значения данных в веб-страницe. LINQ to SQL сверяет исходные значения со значениями в базе данных, прежде чем обновлять или удалять данные. Такой подход может привести к значительному увеличению размера веб-страницы, если запись данных содержит много столбцов или большие значения столбцов. Он также представляет угрозу безопасности, если запись содержит данные, которые нежелательно делать доступными на странице. Когда же в таблице базы данных есть столбец Timestamp, элемент управления LinqDataSource сохраняет для последующего сравнения только значение метки времени. LINQ to SQL может проверять согласованность данных, проверяя исходное значение метки времени на соответствие текущему значению метки времени в базе данных. Дополнительные сведения о временных метках см. в описании типа данных rowversion (Transact-SQL) на веб-узле MSDN.

  • Найдите оптимальное соотношение между преимуществами безопасности и снижением производительности при проверке событий   С помощью элементов управления, являющихся производными от классов System.Web.UI.WebControls и System.Web.UI.HtmlControls, можно проверять, относится ли произошедшее событие к пользовательскому интерфейсу, отрисованному элементом управления. Это позволяет предотвратить ответ элемента управления на поддельное оповещение о событии. Например, с помощью проверки событий элемент управления DetailsView сможет предотвратить совершение злонамеренным пользователем вызова метода Delete (который в этом элементе управления изначально не поддерживается) и удаление данных путем подтасовки. Проверка событий подразумевает определенное снижение производительности. Управлять проверкой событий можно с помощью конфигурационного элемента EnableEventValidation и метода RegisterForEventValidation. Затраты на проверку зависят от количества элементов управления на странице и выражаются невысоким процентным показателем.

    Cc668225.alert_security(ru-ru,VS.100).gifПримечание о безопасности.

    Настоятельно рекомендуется не отключать проверку событий. Перед отключением проверки событий следует убедиться в невозможности создания обратной передачи, способной оказать нежелательное воздействие на работу приложения.

  • Используйте кэширование, сортировку и фильтрацию с помощью элемента управления SqlDataSource   Если для свойства DataSourceMode элемента управления SqlDataSource установлено значение DataSet, элемент управления SqlDataSource может кэшировать результирующий набор запроса. После этого в операциях фильтрации и сортировки элемента управления SqlDataSource можно будет использовать кэшированные данные. Приложение сможет работать быстрее, если кэшировать весь набор данных и использовать для фильтрации и сортировки свойства FilterExpression и SortParameterName. В этом случае элемент управления источником данных сможет обойтись без совершения SQL-запросов с предложениями Where и Sort By для доступа к базе данных каждый раз, когда пользователи сортируют или фильтруют данные в пользовательском интерфейсе.

Веб-приложения

Следующие рекомендации касаются способов обеспечения эффективной работы веб-приложений в целом.

  • Предварительно компилируйте узел   При первом запросе ресурса, например веб-страницы ASP.NET, выполняется пакетная компиляция веб-узла. Если страницы в приложении не скомпилированы, в результате пакетной компиляции все страницы каталога собираются в блоки для оптимизации использования дискового пространства и оперативной памяти. С помощью средства компиляции ASP.NET (Aspnet_compiler.exe) можно предварительно компилировать веб-приложение. В случае компиляции на месте средство компиляции обращается к среде выполнения ASP.NET, чтобы скомпилировать веб-узел таким же образом, как и при запросе пользователем страницы с веб-узла. Предварительная компиляция веб-приложений может выполняться для сохранения разметки пользовательского интерфейса, а предварительная компиляция страниц — для защиты исходного кода от изменения. Дополнительные сведения см. в разделе Практическое руководство. Предварительная компиляция веб-узлов ASP.NET.

  • Отключайте режим отладки   Всегда отключайте режим отладки перед развертыванием конечного приложения или проведением замеров производительности. Включенный режим отладки может снижать производительность приложения. Дополнительные сведения об установке режима отладки см. в разделе Изменение файлов конфигурации ASP.NET.

  • Настраивайте файлы конфигурации под компьютер веб-сервера и под конкретные приложения   По умолчанию конфигурация ASP.NET предусматривает максимально широкий набор включенных функций и рассчитана на самые распространенные сценарии. В зависимости от функций, используемых приложениями, некоторые параметры конфигурации по умолчанию можно изменить с целью повышения производительности приложений. Ниже перечислены возможные изменения конфигурации.

    • Включайте проверку подлинности только для приложений, в которых она необходима   По умолчанию для проверки подлинности в приложениях ASP.NET используется встроенная проверка подлинности Windows. В большинстве случаев наилучшим решением будет отключение проверки подлинности в файле Machine.config и ее включение в файлах Web.config только для нуждающихся в ней приложений.

    • Задайте для приложения соответствующие параметры кодировки запросов и ответов   По умолчанию в ASP.NET используется кодировка UTF-8. Если приложение использует только символы ASCII, небольшое повышение производительности можно обеспечить путем его настройки на кодировку ASCII.

    • Отключайте для приложения режим AutoEventWireup   При установке для атрибута AutoEventWireup в файле Machine.config значения false события страницы не будут привязываться к методам на основе соответствия имени (например, Page_Load). Это обеспечивает некоторое повышение производительности. Для обработки событий страницы используется одна из двух стратегий. Первая стратегия заключается в переопределении методов. Например, можно переопределить метод OnLoad объекта Page для написания кода для события загрузки страницы. (Для обеспечения возникновения всех событий необходимо вызывать базовый метод.) Второй стратегией является привязка к событиям страницы с помощью ключевого слова Handles в Visual Basic или путем подключения делегата в C#.

    • Удаляйте неиспользуемые модули из конвейера обработки запросов   По умолчанию все функции в узле HttpModules в файле Machine.config на серверном компьютере являются активными. В зависимости от того, какие функции используются приложением, можно добиться небольшого повышения производительности путем удаления неиспользуемых модулей из конвейера запросов. Рассмотрите каждый модуль и его функциональность и настройте его для получения желаемых результатов. Например, если в приложении не используются состояние сеанса и кэширование выходного потока, можно удалить соответствующие модули из списка HttpModules.

  • Запускайте веб-приложения в службах IIS 5.0 во внепроцессном режиме   По умолчанию платформа ASP.NET в IIS 5.0 обслуживает запросы с помощью внепроцессного рабочего процесса. Это позволяет повысить пропускную способность. Преимущества и функции выполнения ASP.NET во внепроцессном рабочем процессе позволяют рекомендовать его для рабочих веб-узлов.

  • Периодически перезапускайте процессы   Для повышения надежности и производительности процессы следует периодически перезапускать. Утечка памяти и ошибки в ресурсах за долгое время работы могут негативно повлиять на пропускную способность веб-сервера. Перезапуск процессов устраняет подобные проблемы в работе с памятью. Однако следует учитывать, что слишком частый перезапуск также может снизить пропускную способность, так как остановка рабочего процесса, перезагрузка страниц и повторное получение ресурсов и данных может свести на нет преимущества перезапуска.

    Веб-приложения ASP.NET, выполняемые под управлением Windows Server 2003 и IIS 6.0, не требуют настройки модели процессов, поскольку платформа ASP.NET будет использовать параметры модели процессов IIS 6.0.

  • Задавайте количество потоков для каждого рабочего процесса приложения   Архитектура запросов ASP.NET пытается сбалансировать количество потоков, обслуживающих запросы, и объем доступных ресурсов. Архитектура позволяет одновременно выполнять только то количество запросов, которое соответствует имеющимся ресурсам ЦП. Эта методика называется ограничением потоков. Однако в некоторых случаях алгоритм ограничения потоков работает не слишком хорошо. Отслеживать ограничение потоков можно с помощью монитора производительности Windows, используя счетчик производительности "Число экземпляров конвейеров", связанный с объектом производительности "Приложения ASP.NET".

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

    Для уменьшения подобного неблагоприятного влияния можно вручную установить предельное количество потоков в процессе. Чтобы это сделать, измените атрибуты MaxWorkerThreads и MaxIOThreads в разделе processModel файла Machine.config.

    Cc668225.alert_note(ru-ru,VS.100).gifПримечание.

    Рабочие потоки предназначены для обработки запросов ASP.NET. Потоки ввода-вывода служат для работы с данными из файлов, баз данных или веб-служб ASP.NET.

    Значения, присвоенные атрибутам модели процессов, задают максимальное количество выполняемых потоков каждого типа для одного процессора. Максимальное количество потоков для двухпроцессорного компьютера будет превышать заданное значение в два раза. Максимальное количество потоков для четырехпроцессорного компьютера будет превышать заданное значение в четыре раза. Параметры по умолчанию подходят для одно- и двухпроцессорных компьютеров. Тем не менее, выполнение 100 или 200 потоков в процессе может снизить, а не повысить производительность на многопроцессорных системах. Если количество потоков в процессе слишком велико, процесс может замедлиться. Серверу необходимо выполнять дополнительные операции переключения контекста, в результате чего операционной системе приходится тратить циклы ЦП на обслуживание самих потоков, а не на обработку запросов. Определить оптимальное количество потоков можно с помощью тестирования производительности приложения.

  • Для приложений, активно использующих внешние ресурсы, на многопроцессорных компьютерах включайте режим веб-сада   Модель процессов ASP.NET позволяет реализовать масштабируемость на многопроцессорных компьютерах, распределяя работу между несколькими процессами (по одному для каждого ЦП), каждый из которых привязывается к определенному процессору. Этот прием иногда называют веб-садом. Режим веб-сада благоприятно сказывается на веб-приложениях, интенсивно использующих внешние ресурсы. Сюда можно отнести, например, приложения, использующие сервер баз данных или вызывающие COM-объекты с внешними зависимостями. Тем не менее, перед включением режима веб-сада на рабочем веб-узле следует протестировать приложение в этом режиме на предмет производительности.

Методы создания кода

Следующие рекомендации касаются способов создания эффективного кода.

  • Не полагайтесь в своем коде на исключения   Исключения могут стать причиной значительного снижения производительности, поэтому следует избегать их использования в качестве способа управления нормальным выполнением программы. При возможности в код следует включать логику для обнаружения и обработки условий, в которых возникают исключения. Обычные сценарии для выявления в коде включают проверку на значение null, разбор строк на числовые значения, и проверку на определенные значения перед выполнением математических операций. В следующих примерах приведен код, который может вызывать исключение, и код, проверяющий соответствующее условие. Результат выполнения обоих примеров будет одинаковым.

    // This is not recommended.
    try {
       result = 100 / num;
    }
    catch (Exception e) {
      result = 0;
    }
    
    // This is preferred.
    if (num != 0)
       result = 100 / num;
    else
      result = 0;
    

    ' This is not recommended.
    Try
       result = 100 / num
    Catch (e As Exception)
      result = 0
    End Try
    
    ' This is preferred.
    If Not (num = 0)
       result = 100 / num
    Else
      result = 0
    End If
    
Показ: