Советы по производительности для классического asp?

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

Страница состоит из базового "SELECT bla bla FROM bla" на пару наборов записей. Цикл while выполняет итерацию по этим наборам записей и выводит строки <tr> <td>. Внутри цикла while есть множество условных выражений и еще много чего. Вызываются 3 подпрограммы, которые используют глобальные переменные (а не локальные переменные, передаваемые в качестве параметров).

Так что ничего шокирующего или чего-то такого. До того, как я начал оптимизацию, цикл длился около 15 секунд. Из 15 секунд около 6 были заняты запросом sql.

После изменения нескольких вещей мне удалось добиться 7 секунд.

Я изменил следующее:

  • Вместо того, чтобы делать SELECT *, я выбрал только нужные мне столбцы. Запрос снизился в среднем до 4 секунд. Это довольно сложный запрос с представлениями внутри представлений.

  • Я удалил все переключение контекста в цикле. Поэтому я изменил такие вещи, как <% = bla%> на Response.Write (bla).

  • 3 подпрограммы были определены как функции, но они использовались как подпрограммы (безрезультатно). Поэтому я изменил функции на подпрограммы. Это помогает?

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

  • Функции даты: Dateadd, Datediff
  • Функции массива: Ubound (arr) и ссылка на индекс: arr (I)
  • Строковые функции: left, mid, right, lower, replace

При каждом вызове страницы эта подпрограмма запускается около 1600 раз.

Кто-нибудь имеет опыт оптимизации классических asp-страниц? Есть ли у вас какие-нибудь полезные советы по оптимизации? Я ищу улучшение кода в операторе do ... loop.

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

Спасибо!

M

PS: Да, я знаю, что классический ASP использует VBScript

Ответов (6)

Решение

GetRows Это обеспечит желаемую скорость. Вот еще несколько советов, которые я использовал.

Видя, что это популярный вопрос, я решил объяснить, что я сделал 3 года назад, что ускорило сценарий ASP.

В исходном скрипте для хранения ключей и значений широко использовались массивы с изменяемым размером, поэтому я изменил этот код, чтобы использовать Scriting.Dictionary. Пример:

Dim myDictionary
Set myDictionary = Createobject("Scripting.Dictionary") 
myDictionary.item("key") = "value"

Это намного быстрее, чем массивы с изменяемым размером.

Еще одно большое изменение - конкатенация строк. Исходный сценарий был полон:

S = ""
S = S & "First line<br />"
S = S & "Second line<br />"
S = S & "Third line line<br />"
Response.Write(S)

Я изменил это на:

Response.Write("First line<br />")
Response.Write("Second line<br />")
Response.Write("Third line<br />")

Это имело огромное значение. Объединение строк является огромным узким местом, потому что строка выбрасывается, а затем повторно инициализируется.

Другой вариант:

S = "First line<br />" & _
        "Second line<br />" & _
        "Third line line<br />" 
Response.Write(S)

Это также хороший совет для ASP.NET: используйте StringBuilder вместо объединения строк.

Еще одно важное изменение - переключение контекста. Исходный код был полон:

<table>
    <tr>
        <td><%= rs("Col1") %></td>
        <td><%= rs("Col2") %></td>
        <td><%= rs("Col2") %></td>
    </tr>
</table>

Три переключателя контекста занимают много времени, поэтому я изменил его так:

<%
Response.Write("<table>")
Response.Write("<tr>")
Response.Write("<td>")
Response.Write(rs("Col1"))
Response.Write("</td>")
Response.Write("</tr>")
Response.Write("<tr>")
Response.Write("<td>")
Response.Write(rs("Col2"))
Response.Write("</td>")
Response.Write("</tr>")
Response.Write("<tr>")
Response.Write("<td>")
Response.Write(rs("Col3"))
Response.Write("</td>")
Response.Write("</tr>")
Response.Write("</table>")
%>

Да, код очень избыточен, но работает лучше.

Еще одна небольшая модификация (которая на самом деле является грязным взломом) - использовать WITH (NOLOCK) в ваших SQL-запросах:

conn.Query("SELECT * FROM MyTable WITH (NOLOCK) LEFT JOIN AnotherTable WITH (NOLOCK) ON MyTable.Id = AnotherTable.Id")

Это имеет значение.

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

Я надеюсь, что люди, нашедшие эту статью, найдут эти советы полезными.

При каждом вызове страницы эта подпрограмма запускается около 1600 раз.

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

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

Я испытал, что в большинстве случаев вы можете повысить производительность при использовании StringBuilder в классическом ASP. В библиотеке ajaxed есть хорошая реализация StringBuilder для классического ASP . Он использует .net StringBuilder. Это довольно круто и просто в использовании:

<%
set output = new StringBuilder
do
  output("some output")
loop
response.write(output.toString())
%>

Я бы рекомендовал использовать библиотеку ajaxed, если вам нужно немного настроить. Он быстро настраивается и предлагает множество инструментов для классического ASP. Например, возможно, вы могли бы также получить некоторую производительность при использовании AJAX (или, по крайней мере, впечатление производительности).

Я отмечаю ответ MrChrister как ответ на мой вопрос «Есть ли у вас какие-нибудь полезные советы по оптимизации?». Советы там хорошие, и скрипт удалось ускорить на 2 секунды.

В конце концов я выяснил, что замедляет работу сценария. В цикле while программист много работал с фильтром (массивом). Он в основном использовал фильтр (массив) для поиска пар ключ / значение.

Таким образом, окончательным решением было изменение кода Filter (Array) на использование объекта Scripting.Dictionary. Это ускорило код в 12 раз.

Спасибо за все ваши ответы.

M