Важной частью цикла разработки Microsoft является настройка производительности продукта. Настройка производительности также является одной из ключевых областей, на которую следует обратить внимание разработчикам. За годы разработок отрасль узнала много нового о том, как оптимизировать производительность программ Win32.
Одна из проблем, с которыми сегодня сталкиваются разработчики, заключается в том, что они не совсем понимают, что заставляет страницы DTHML и HTML работать быстро или медленно. Конечно, есть несколько простых решений — например, не использовать изображения размером 2 МБ. Мы использовали некоторые другие интересные методы для повышения производительности страниц DHTML. Мы надеемся, что они помогут вам улучшить производительность ваших собственных страниц.
Здесь я использую пример программы для создания таблицы. Методы document.createElement() и element.insertBefore() используются для создания таблицы из 1000 строк (Row). Каждая строка имеет один столбец (Ячейка). Содержимое, содержащееся в ячейке, называется «Текст». Насколько плохим может быть этот код? Насколько велика возможность корректировки такой маленькой программы? Пожалуйста, ознакомьтесь с введением.
Вначале я написал программу, которая, как мне казалось, будет быстрой, и старался избежать некоторых проблем низкого уровня, таких как отсутствие явного определения переменных или одновременное использование VBScript и JavaScript на одной странице. Программа выглядит следующим образом:
<html>
<тело>
<скрипт>
вар tbl, tbody, tr, td, текст, я, макс;
макс = 1000;
таблица = document.createElement("ТАБЛИЦА");
таблица.граница = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
для (я=0; я<макс; я++) {
tr = document.createElement("TR");
td = document.createElement("TD");
текст = document.createTextNode("Текст");
td.insertBefore(текст, ноль);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</скрипт>
</тело>
</html>
Запустите эту программу на компьютере с памятью PII233/64 МБ/NT4.0/IE5.0. Страница загружается с этого компьютера. Время от начала загрузки страницы до ее полного успокоения (все события выполнены и отображение экрана завершено) составляет 2328 миллисекунд, что также является базовым показателем этого теста (я называю его Тест1).
На этой странице очень трудоемкая операция — частое обращение к глобальным объектам, таким как «документ», «тело», «окно» и т. д. Ссылка на все эти похожие глобальные переменные обходится гораздо дороже, чем ссылка на одну локальную переменную.
Итак, я сделал первую попытку улучшения: кэшировал (Cache) document.body в локальную переменную «theBody»:
добавил следующий код:
var theBody = document.body;
Затем измените эту строку:
document.body.insertBefore(tbl, null);
Измените его на:
theBody.insertBefore(tbl, null);
Посмотреть второй пример
Эта модификация не сильно повлияла на общее время, сократила лишь 3 мс. Но было показано, что если в цикле также имеется объект document.body и его ссылка изменена, преимущества будут значительными.
Впоследствии я кэшировал объект документа — в нашем тесте к объекту документа обращались всего 3002 раза. Модифицированный код выглядит следующим образом:
<html>
<тело>
<скрипт>
вар tbl, tbody, tr, td, текст, я, макс;
макс = 1000;
вар theDoc = документ;
вар theBody = theDoc.body
tbl = theDoc.createElement("ТАБЛИЦА");
таблица.граница = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
для (я=0; я<макс; я++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Текст");
td.insertBefore(текст, ноль);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</скрипт>
</тело>
</html>
Посмотрите третий пример.
Это время работы составляет всего 2100 мс, что позволяет сэкономить около 10% времени. Использование локальных переменных вместо прямой ссылки на объект документа каждый раз экономило в среднем 0,4 миллисекунды.
Распространенным способом оптимизации производительности является установка атрибута «defer» в теге <SCRIPT>, когда сценарий не требуется запускать немедленно. (Непосредственный сценарий не содержится в функциональном блоке, поэтому он будет выполнен во время процесса загрузки.) После установки атрибута «defer» IE не нужно ждать загрузки и выполнения сценария. Таким образом страница будет загружаться быстрее. Вообще говоря, это также означает, что непосредственные сценарии лучше всего размещать в функциональных блоках и обрабатывать функцию в обработчике загрузки документа или объекта тела. Это свойство полезно, когда есть некоторые сценарии, которые необходимо выполнить на основе действий пользователя, например, нажатия кнопки или перемещения мыши в определенную область. Но когда есть некоторые сценарии, которые необходимо выполнить во время или после загрузки страницы, преимущества использования атрибута defer невелики.
Ниже представлена модифицированная версия кода с использованием атрибута defer:
<html>
<body onload="init()">
<отсрочка сценария>
функция инициализации() {
вар tbl, tbody, tr, td, текст, я, макс;
макс = 1000;
вар theDoc = документ;
вар theBody = theDoc.body
tbl = theDoc.createElement("ТАБЛИЦА");
таблица.граница = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
для (я=0; я<макс; я++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Текст");
td.insertBefore(текст, ноль);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</скрипт>
</тело>
</html>
Просмотр четвертого примера.
Время этого теста составляет 2043 мс. Это увеличение на 12% по сравнению с базовым тестом и на 2,5% выше, чем в предыдущем тесте.
Метод улучшения, о котором мы поговорим ниже, конечно, очень полезен, но немного более хлопотный. Когда вам нужно создать элемент, а затем вставить его в древовидную структуру, более эффективно вставить его непосредственно в ствол, а не сначала вставлять его в большое поддерево, а затем вставлять большое поддерево в ствол. Например, если вы создаете таблицу с одним столбцом в каждой строке и некоторым текстом в столбце, вы можете сделать следующее:
1. Создать <TR>
2. Создать <TD>
3. Создать узел TextNode
4. Вставить TextNode в <TD >
5. Вставьте <TD> в <TR>
6. Вставьте <TR> в TBODY
Если он медленнее, чем следующий метод:
1. Создайте <TR>
2. Создайте <TD>
3. Создайте TextNode
4. Вставьте <TR > Вставить в TBODY
5. Вставить <TD> в <TR>
6. Вставить TextNode в <TD>
Все четыре теста используют первый метод. Последний метод мы использовали для пятого теста. Код следующий:
<html>
<body onload="init()">
<отсрочка сценария>
функция инициализации() {
вар tbl, tbody, tr, td, текст, я, макс;
макс = 1000;
вар theDoc = документ;
вар theBody = theDoc.body
tbl = theDoc.createElement("ТАБЛИЦА");
таблица.граница = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
для (я=0; я<макс; я++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Текст");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore(текст, ноль);
}
}
</скрипт>
</тело>
</html>
Просмотр пятого примера.
Test5 занимает всего 1649 мс. Это на 25 % лучше, чем в последнем тесте, и почти на 30 % быстрее, чем базовый уровень.
Последующие изменения были сделаны с использованием готовых таблиц стилей. Ширина столбца таблицы, которая использует готовую таблицу стилей или задается с помощью тега <COL>. При отсутствии тега <COL> ширина каждого столбца распределяется равномерно. Поскольку нет необходимости пересчитывать размер каждого столбца и т. д., использование таблицы стилей фактически повышает производительность, особенно когда количество столбцов в таблице велико.
Код для добавления таблицы стилей (CSS) очень прост:
tbl.style.tableLayout = «fixed»;
Просмотрите шестой пример.
Поскольку в таблице нашего теста был только один столбец, это изменение повысило производительность страницы только на 1,6%. Если столбцов будет больше, прирост производительности будет еще больше.
Последние два теста изменили способ вставки текста в таблицу. В предыдущих тестах мы сначала создавали TextNode, а затем вставляли его в TD. Вместо этого в Test7 мы указываем включенный текст через внутренний текст. Измененный код:
td.innerText = "Текст";
Посмотрите седьмой образец
Удивительно, но разница, которую произвела эта модификация, была огромной — улучшение производительности на 9% по сравнению с предыдущим периодом и общее улучшение производительности на 36% по сравнению с оригиналом. Время варьируется от первых 2323 мс до последних 1473 мс.
Теперь почти все знают, что использование element.innerHTML очень медленное. Чтобы увидеть, насколько это медленно, я провел последний тест: вставку текста с использованием InnerHTML вместо InnerText. Это сильно снижает производительность. Время достигло 3375 мс, что на 80 % медленнее, чем в последнем тесте, и на 45 % медленнее, чем в базовом тесте. Очевидно, что использование InternalHTML требует очень много времени.
Настройка производительности HTML-страницы аналогична настройке производительности приложения Win32: вам нужно знать, что работает медленно, а что быстро; Я надеюсь, что эти методы помогут вам улучшить производительность страницы.