Глава 8. Приложение

8.1. Обзор аналитических инструментов

Давайте рассмотрим ряд приемов, позволяющих самостоятельно провести анализ производительности сайта. К ним можно отнести как проверку времени создания страницы на сервере, так и измерение фактического времени загрузки страницы у пользователя.

Измеряем эффективную ширину канала пользователей

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

Прежде чем давать браузеру любые ссылки на внешние объекты (, ,

Эта конструкция произведет примерно следующую запись в лог-файл:

127.0.0.1 - - [28/Oct/2006:13:47:45 -0700]

"GET /timer.gif?u=http://example.com/page.html&t=0.971 HTTP/1.1" 200 49 ...

В этом случае, как можно понять из записи, загрузка оставшейся части страницы http://example.com/page.html заняла у пользователя 0,971 секунды. Если предположить, что всего на странице было загружено файлов общего размера в 57842 байтов, 57842 байтов * 8 битов в байте / 0,971 секунды = 476556 битов в секунду (4б5 Кбит). Такова эффективная пропускная способность канала при загрузке этой страницы. Если у пользователя физический входящий канал 1,5 Мб, значит есть большой простор для увеличения скорости загрузки.

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

Apache Benchmark и JMeter

Утилита ab из пакета для Apache (устанавливается под Linux обычно вместе с самим Apache) позволяет устроить простой тест для производительности сервера. Стоит заметить, что это будет чисто серверная производительность, а не клиентская.

Мы можем запустить тест с помощью команды

ab –c10 –n1000 http://www.website.ru/

Вышеуказанным способом мы запускаем стресс-тест для сайта www.website.ru. При проведении тестирования главная страница сайта будет скачана 1000 раз (модификатор –n1000) с использованием 10 параллельных соединений (модификатор –c10). Если запустить такой же тест для статических файлов, то можно диагностировать медленное обслуживание обычных запросов (обычно статические файлы отдаются со скоростью порядка 1000 в секунду). Если же сервер отвечает дольше, чем 5-10 миллисекунд при генерации страницы, значит стоит хорошо разобраться, на что уходит процессорное время.

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

Time per request: 40.599 [ms]

Connection Times (ms)

min mean[+/-sd] median max

Connect:184012.53861

Processing:000.301

Waiting:00 0.301

Total:184112.43861

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

К такому нагрузочному тестированию стоит подходить крайне осмотрительно: не запускать его на том же самом сервере, где располагается исследуемый сайт (ибо ab сам по себе достаточно «тяжелый» и будет делить физические ресурсы машины с Apache). Если в результате таких тестов задержки оказались весьма высокими и процесс веб-сервера (или CGI) «отъедал» слишком много CPU, то причиной этого зачастую может оказаться необходимость в компиляции скриптов в процессе выполнения при каждом запросе.

Для более мощного и точного тестирования стоит посмотреть в сторону другой программы — Apache JMeter, которая предназначена для нагрузочного тестирования различных сетевых сервисов и приложений, не ограничиваясь только HTTP. Это по сути универсальная и более продвинутая замена ab, только более требовательная к пользователю, так как содержит ряд мощных инструментов, правильно применить которые под силу только профессионалу. Кстати, JMeter позволяет не только тестировать веб-приложения, но и любые другие сетевые сервисы — SMTP, POP и даже базы данных через JDBC. Если в планах стоит постоянное использование тестирования, то стоит обратить внимание именно на это приложения: из бесплатных и открытых — это, пожалуй, самое гибкое и мощное решение.

Кэширование на сервере

Такое программное обеспечение, как eAccelerator/xCache/ZendOptimizer для PHP, mod_perl для perl, mod_python для python и др., могут кэшировать серверные скрипты в скомпилированном состоянии, существенно ускоряя загрузку нашего сайта. Кроме этого, стоит найти профилирующий инструмент для используемого языка программирования, чтобы установить, на что же тратятся ресурсы CPU. Если удастся устранить причину больших нагрузок на процессор, то страницы будут отдаваться быстрее и появится возможность выдавать больше трафика при меньшем числе машин.

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

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

Web Developer Toolbar для Firefox

Данный инструмент позволяет проанализировать размеры всех загруженных на странице файлов (чтобы его открыть, нужно кликнуть или выбрать через правый клик панель инструментов Web Developer -> Information -> View Document Size). Можно посмотреть на список файлов и оценить, что отнимает большую часть времени при загрузке страницы:

Рис. 8.1. Результаты анализа загрузки сайта в Web Developer Toolbar

К сожалению, здесь размер встроенных изображений отображается неверно. И нет данных о том, в какую стадию загрузки попал той или иной файл. Работает только под Firefox.

Firebug NET Panel для Firefox

Другим, более популярным инструментом для анализа загрузки сайта в Firefox является Firebug (со встроенной NET Panel). Он отслеживает все пакеты, которые передает или запрашивает Firefox, позволяя тем самым построить вполне точную диаграмму загрузки страницы. Естественно, позволяет увидеть и все HTTP-заголовки (как запроса, так и ответа) для полученных файлов. К сожалению, на данный момент Firebug не учитывает время, затраченное на DNS-запросы, редиректы и отображение страницы.

Однако ситуация обещает исправиться, да еще и кардинальным образом: уже сейчас доступна альфа-версия Firebug 1.4a1, в которой для каждого загружаемого объекта страницы теперь выводится полная статистика затрачиваемого времени. Конечно, есть еще куда стремиться: можно добавить и общую диаграмму загрузки, и затраты времени на все компоненты вместе, а не по отдельности. Но и этот шаг будет весьма значительным.

Рис. 8.2. Результаты анализа загрузки сайта в Firebug Net Panel 1.4a1

На этой диаграмме теперь можно увидеть, когда же наша страница считается загруженной как частично, так и полностью (первая и третья стадии загрузки соответственно): две вертикальные линии синего и красного цвета показывают моменты событий DOMContentLoaded и самого load. Очевидно, что после события load могут происходить дополнительные загрузки компонентов, которые находятся в четвертой стадии, что, естественно, не всегда совпадает с фактической загрузкой и отображением компонентов страницы.

Но давайте рассмотрим загрузку страницы в текущей версии инструмента:

Рис. 8.3. Результаты анализа загрузки сайта в Firebug Net Panel

На диаграмме загрузки для webo.in хорошо отслеживается стадия предзагрузки (заканчивающаяся c получением файла c.css?20081010). На этой же стадии у пользователя оказываются загруженными 2 изображения (оба запрошены через new Image().src, одно из них — «на будущее). После того как страница появилась в браузере пользователя (на это ушло порядка 200 мс с момента запроса страницы), сработало событие готовности документа к дальнейшим действиям. По этому событию Firefox запросил 3 файла: d.css?20081010, g.js?20080920 и j.js?20080924.

g.js (являясь сжатым скриптом Google Analytics) отправил данные о посещении на сервер статистики с помощью файла __utm.gif . Стоит заметить, что все вызовы внешних ресурсов из HTML-файла осуществлялись при использовании DOM-методов добавления элементов, и это позволило максимально их распараллелить. Далее Firefox (так как кэш был отключен) запросил файл b.png повторно (основываясь уже на данных из файла d.css, содержащего информацию о стилях для фона элементов). При наличии в кэше файл просто отобразился бы на странице, и запроса не произошло.

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

В данном случае размер страницы составляет порядка 100 Кб в сжатом виде и около 200 Кб в несжатом. Однако это не помешало ей загрузиться (если не брать в расчет некоторые файлы «на будущее» и отключенное кэширование) менее чем за 500 мс.

Yslow для Firebug для Firefox

В качестве полезного дополнения к Firebug (для Firefox) стоит рассмотреть и YSlow. На данный момент этот инструмент, пожалуй, является наиболее адекватным для анализа скорости загрузки страницы.

Все аспекты производительности разбиты на разделы. В случае невыполнения каких-либо советов дается ссылка на полный его вариант на английском языке. Естественно, что советы не идеальны, и в некоторых случаях допустимо не следовать им буквально. Однако при прочих равных условиях более высокая оценка (максимум 100) соответствует более оптимизированному сайту (рис. 8.4).

Рис. 8.4. Результаты анализа загрузки сайта в YSlow

Web Inspector для Safari

Аналогично уже рассмотренной Firebug Net Panel, Web Inspector представляет диаграмму загрузки, основываясь на фактических данных. Однако есть и ряд недостатков: в частности, время отображения (выполнения) элемента не отделено от времени его загрузки, что хорошо видно для встроенных изображений (рис. 8.5).

Рис. 8.5. Результаты анализа загрузки сайта в Web Inspector

HttpWatch

HttpWatch ( http://www.httpwatch.com/ ) может быть установлен как для IE, так и для Firefox. На данный момент кроме самих HTTP-заголовков он предоставляет достаточно подробную диаграмму загрузки сайта, что является хорошим подспорьем при анализе производительности (рис. 8.6).

Рис. 8.6. Результаты анализа загрузки сайта в Http Watch

Полная версия продукта является платной.

Fiddler

Fiddler ( http://www.fiddlertool.com/fiddler/ ) устанавливается как дополнение к IE и позволяет анализировать все загружаемые файлы (заголовки, размер, время загрузки из разных точек земного шара) (рис. 8.7).

Рис. 8.7. Результаты анализа загрузки сайта в Fiddler

Live HTTP Headers

Live HTTP Headers ( http://livehttpheaders.mozdev.org/ ) позволяет просматривать HTTP-заголовки для Firefox в режиме реального времени. Может выступать достаточно удобным дополнением в Firefox, если нужно отладить общение браузера с сервером в плане кэширования или сжатия (проверить соответствующие заголовки на «живом» соединении) (рис. 8.8).

Рис. 8.8. Заголовки запроса и ответа в Live HTTP Headers для webo.in

Прокси-эмулятор каналов Sloppy

После рассмотрения всех методов ускорения загрузки стоит заметить, что та или иная техника оптимизации направлена в первую очередь на пользователей с медленным каналом — именно они в наибольшей мере почувствуют выигрыш от наших кропотливых манипуляций с проектом. Но как же проверить это еще на этапе разработки — ведь в большинстве случаев тестовый сервер располагается на рабочем компьютере, да и интернет-канал у профессиональных веб-разработчиков тоже не самый плохой. Выход есть: эмулировать такие соединения, подключаясь через специальную программу, которая нарочно «затормозит» (но не Интернет, а только доступ к тестовому сайту) соединение, имитируя подключение пользователя, скажем, с ADSL-128 Kbps.

Для этого нам подойдет небольшая и очень простая программа Sloppy — прокси-сервер. Он эмулирует доступ к указанному сайту через канал с задаваемой полосой пропускания: от модемного 9,6 Кб/с до выделенного в 512 Кб/с. В том случае, если скорость подключения к интернету 1 Мб или больше, любой проект будет загружаться достаточно быстро, поэтому тестировать его специально не имеет смысла (только в общем порядке). А влияние издержек на установление множества дополнительных соединений можно установить при тестировании на менее мощных каналах.

Из доступных настроек у нас есть: адрес сайта, который будем тестировать, выбор скорости (из набора 9.6, 14.4, 28.8, 56, 128, 256 и 512 Кб), а также порт, по которому мы будем получать страницу. Благодаря «прокси-природе» его можно использовать для тестирования как локального проекта, так и любого внешнего проекта в сети. Конечно, в этом случае нужен доступ в Интернет, тогда как просто для теста локального сервера этого совсем не требуется (после загрузки самого приложения).

Sloppy интересен еще и тем, что распространяется как JNLP-файл, то есть использует Java Web Start для запуска; при этом сам код загружается с сайта проекта, впрочем, можно загрузить исходный код отдельно.

Рис. 8.9. Настройки Sloopy для тестирования загрузки сайта на медленном канале

Analyze.WebSiteOptimization.com

Пожалуй, самый старый и наиболее известный онлайн-сервис для проверки клиентской оптимизации выбранного сайта. Выдает набор советов (аналогичных рекомендациям Yahoo). Поскольку анализ основан на собственном алгоритме, то не распознает data:URI и mhtml-изображения. Также не всегда верно трактует скрипты внутри страницы.

Рис. 8.10. Результаты анализа загрузки сайта в analyze.websiteoptimization.com

Octagate.com/service/SiteTimer/

С помощью данного инструмента можно построить диаграмму загрузки сайта. К плюсам можно отнести то, что дополнительно показан RSS-поток (при соответствующем объявлении). К несчастью, сервис не распознает data:URI и mhtml-изображения; также построение самой диаграммы загрузки оставляет желать лучшего.

Рис. 8.11. Результаты анализа загрузки сайта в octagate.com/service/sitetimer/

Tools.Pingdom.com

Сервис позиционирует себя как инструмент для построения диаграммы загрузки, однако на данный момент не распознает сжатия файлов и выделения фоновых картинок (рис. 8.12).

Рис. 8.12. Результаты анализа загрузки сайта в tools.pingdom.com

AlertSite.com

Сервис позиционирует себя как инструмент для построения диаграммы загрузки, однако, на данный момент не распознает сжатия файлов, data:URI и mhtml-файлы. Также есть проблемы с распознаванием таблиц стилей. Однако, для всех файлов выводится достаточно большое число параметров, характеризующих процесс загрузки (рис. 8.13).

Рис. 8.13. Результаты анализа загрузки сайта в www.alertsite.com/cgi-bin/tsite3.pl

Site-Perf.com

Относительно недавно появившийся сервис, который предлагает комплексный анализ скорости загрузки сайта. Он позволяет оценить как узкие места при загрузке, так и общий «вес» страницы. Возможно моделирование процесса загрузки при использовании нескольких параллельных соединений. Также есть возможность выбрать одну из нескольких тестовых точек.

К минусам можно отнести невозможность распознавания динамических файлов стилей и скриптов, а также условных комментариев.

Рис. 8.14. Результаты анализа загрузки сайта в site-perf.com

GetRPO.com

На данный момент разрабатываются уже и автоматизированные решения для уменьшения времени загрузки страницы. Одним из таких сервисов является Runtime Page Optimizator, который позволяет (в автоматическом режиме для IIS) уменьшить время загрузки страницы. Также есть возможность запросить проверку требуемого сайта и получить вполне детальный анализ, что и как можно сделать для ускорения его загрузки. Поскольку для анализа используется встроенный браузер (MSIE), то результаты проверки наиболее достоверны (рис. 8.15).

Рис. 8.15. Результаты анализа загрузки сайта в get-rpo.com

Webo.in

Web Optimizator — единственный на данный момент русскоязычный ресурс, посвященный клиентской оптимизации. При анализе сайта выдается как общая характеристика, так и конкретные советы по возможному ускорению его загрузки (рис. 8.16).

Рис. 8.16. Результаты анализа загрузки сайта в webo.in

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

Рис. 8.17. Результаты анализа загрузки сайта в webo.in (диаграмма загрузки)

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

Дополнительно к анализу производительности можно автоматически уменьшить и объединить все тестовые файлы и оптимизировать в размере графику с помощью «Пакетной оптимизации». Этот сервис работает как с уже проверенными сайтами, последовательно загружая и оптимизируя все файлы, так и с архивами.

К недостаткам Web Optimizator стоит отнести отсутствие распознавания динамической загрузки ресурсных файлов (например, через DOM-методы).

Профилирование JavaScript

JSLint ( http://www.jslint.com/ ) позволяет проанализировать код и убедиться в том, что он корректно отформатирован. Очень часто структурные ошибки или неверное форматирование кода пагубно сказываются на дальнейшем его уменьшении, ибо все минимизаторы обладают собственным синтаксическим аппаратом, они не используют браузеры для проверки корректности JavaScript. Поэтому, не проверив код на соответствие стандартам, есть все шансы получить его после уменьшения или обфускации неработающим.

JsUnit ( http://www.jsunit.net/ ) предоставляет мощный фреймворк для тестирования и отладки ваших JavaScript-приложений. С помощью AjaxView ( http://research.microsoft.com/projects/ajaxview/ ) можно проксировать и анализировать AJAX-запросы. Для профессионального профилирования веб-приложений стоит воспользоваться JsLex ( http://rockstarapps.com/pmwiki/pmwiki.php?n=JsLex.JsLex ), а время выполнения различных операций на странице можно замерить с помощью YUI Profiler ( http://developer.yahoo.com/yui/profiler/ ). Но не стоит забывать, что лучшей проверкой веб-приложений на прочность всегда был и остается пользователь.

8.2. Несколько советов для браузеров

Ускоряем загрузку страниц в Firefox 3

В Firefox можно увеличить скорость загрузки и отображения страниц, значительно повысив комфортность работы в Интернете. Что для этого нужно сделать:

Открыть страничку настроек, набрав в адресной строке about:config.

Отредактировать следующие опции:

network.http.pipelining — true

network.http.proxy.pipelining — true

network.http.pipelining.maxrequests — 8

nglayout.initialpaint.delay — 0

(в последнем случае необходимо щелкнуть правой кнопкой и создать новое целое значение с таким именем).

Все, теперь можно наслаждаться возросшей скоростью загрузки и отображения (особенно заметно на широких каналах).

Как это работает?

В протоколе HTTP версии 1.1, внедренном в 1999 году и используемом по сей день во Всемирной паутине, появилась возможность в рамках одного TCP-соединения делать несколько запросов веб-серверу.

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

network.http.version — 1.1, network.http.keep-alive — true

Эти опции установлены по умолчанию и разрешают Firefox использовать HTTP версии 1.1, включая возможность делать несколько запросов в соединении.

network.http.pipelining — true, network.http.proxy.pipelining — true

Эти опции предписывают Firefox делать несколько запросов в соединении, не дожидаясь ответа сервера. Фактически, мы начинаем использовать HTTP-конвейер на полную мощность. Но нужно понимать, что не все веб-серверы на текущий момент поддерживают эту технологию и в некоторых случаях возможны проблемы с загрузкой ресурсов.

network.http.pipelining.maxrequests — 8

Эта опция задает максимальное количество запросов, которое может быть сделано в соединении: от 1 до 8. Указывать значение более 8 бессмысленно, так как это физически не поддерживается Firefox и эффекта иметь не будет.

nglayout.initialpaint.delay — 0

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

Ускоряем загрузку страниц в Opera 9

В Opera также имеется ряд настроек, которые пользователь может легко изменить. Для этого нужно зайти на страницу opera:config, на которой все необходимые параметры можно легко найти с помощью поиска. Итак, рекомендуется выставить следующие значения:

Max Connections Server = 16

Устанавливает число параллельных соединений с одним хостом. Подробнее о влиянии числа используемых соединений на скорость загрузки рассказывается в пятой главе.

Max Connections Total = 32 или 64

Устанавливает максимальное число открытых соединений (с различными хостами для одной страницы).

Check local Hostname отключить

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

Always load favicon = 0

favicon.ico (как было описано во второй главе) оказывает существенное влияние на скорость загрузки. Если используется медленное подключение к Интернету, то загрузку иконки сайта можно отключить. Это позволит быстрее загружать действительно нужные файлы (например, таблицу стилей).

Documents Expiry = 3600

По умолчанию Opera кэширует HTML-файлы на 5 минут (300 секунд). При увеличении этого времени до 1 часа браузер не будет лишний раз запрашивать сервер, а просто возьмет документ из кэша.

Images Expiry = 86400

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

Other Expiry = 86400

Здесь речь идет о других статических файлах. Для них также можно выставить кэширование на сутки.

Delayed Script Execution включить

Отложенное выполнение скриптов позволяет Opera начать отображение страницы сразу по получению HTML-файла (и всех CSS-файлов, если они загрузятся достаточно быстро). При загрузке JavaScript Opera просто перерисует страницу в браузере. Эта функциональность способна существенно ускорить загрузку страницы, однако при значительных изменениях при загрузке скриптов может ухудшать восприятие сайтов: не всегда приятно, если страница меняется раз в секунду.

После изменения всех настроек нужно их сохранить и перезапустить Opera.

Также можно попробовать уменьшить задержку при перерисовке страницы. Для этого нужно выбрать (англоязычная версия):

Tools -> Preferences -> Advanced -> Browsing -> Loading –> Redraw instantly

В русскоязычной:

Инструменты -> Настройки -> Дополнительно -> Обозреватель ->

Перерисовывать страницу –> Непрерывно

Interner Explorer

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

Мы должны зайти в реестр (например, через Пуск -> Выполнить -> regedit) и пройти в следующую ветку:

HKEY_CURRENT_USER -> Software -> Microsoft -> Windows -> Current version ->

Internet settings

Там нужно создать 2 новых параметра (DWORD) с названиями MaxConnectionsPer1_0Server и MaxConnectionsPerServer. У обоих изменить значение (Правый клик -> Изменить) на 10. Здесь стоит заменить, что, по умолчанию, значение выводится в шестнадцатеричной системе счисления, что соответствует 16 в десятичной. Таким образом, мы выставим число максимальных соединений к одному хосту равным 16.

После этого остается только перезапустить IE и наслаждаться быстрым интернетом.

8.3. Оптимизированные конфигурации

Конфигурация Apache 1.3

# включаем gzip

mod_gzip_on Yes

# если рядом с запрашиваемым файлом есть сжатая версия с расширением .gz, то

# будет отдана именно она, ресурсы CPU расходоваться не будут

mod_gzip_can_negotiate Yes

# используем при статическом архивировании расширение .gz

mod_gzip_static_suffix .gz

# выставляем заголовок Content-Encoding: gzip

AddEncoding gzip .gz

# выставляем минимальный размер для сжимаемого файла

mod_gzip_minimum_file_size 1000

# и максимальный размер файла

mod_gzip_maximum_file_size 500000

# выставляем максимальный размер файла, сжимаемого прямо в памяти

mod_gzip_maximum_inmem_size 60000

# устанавливаем версию протокола, с которой будут отдаваться gzip-файлы

# на клиент

mod_gzip_min_http 1000

# исключаем известные проблемные случаи

mod_gzip_item_exclude reqheader "User-agent: Mozilla/4.0[678]"

mod_gzip_item_exclude reqheader "User-agent: Konqueror"

# устанавливаем сжатие по умолчанию для файлов .html

mod_gzip_item_include file \.html$

# включаем .css / .js файлы, подробнее о них ниже

mod_gzip_item_include file \.js$

mod_gzip_item_include file \.css$

# дополнительно сжимаем другие текстовые файлы

mod_gzip_item_include mime ^text/html$

mod_gzip_item_include mime ^text/plain$

mod_gzip_item_include mime ^httpd/unix-directory$

# отключаем сжатие для картинок (не дает никакого эффекта)

mod_gzip_item_exclude mime ^image/

# отключаем 'Transfer-encoding: chunked' для gzip-файлов, чтобы

# страница уходила на клиент одним куском

mod_gzip_dechunk Yes

# добавляем заголовок Vary для корректного распознавания браузеров,

# находящихся за локальными прокси-серверами

mod_gzip_send_vary On

# запрещаем прокси-серверам кэшировать у себя сжатые версии файлов

Header set Cache-Control: private

# включаем кэширование для всех файлов сроком на 10 лет

ExpiresActive On

ExpiresDefault "access plus 10 years"

# отключаем его для HTML-файлов

ExpiresActive Off

Конфигурация Apache 2

# выставляем заголовок Content-Encoding: gzip

AddEncoding gzip .gz

# с самого начала включаем gzip для текстовых файлов

AddOutputFilterByType DEFLATE text/html

AddOutputFilterByType DEFLATE text/xml

# и для favicon.ico

AddOutputFilterByType DEFLATE image/x-icon

# также для CSS- и JavaScript-файлов

AddOutputFilterByType DEFLATE text/css

AddOutputFilterByType DEFLATE text/javascript

AddOutputFilterByType DEFLATE application/x-javascript

# далее устанавливаем максимальную степень сжатия (9)

# и максимальный размер окна (15). Если сервер не такой мощный,

# то уровень сжатия можно выставить в 1, размер файлов при этом

# увеличивается примерно на 20%.

DeflateCompressionLevel 9

DeflateWindowSize 15

# отключаем сжатие для тех браузеров, у которых проблемы с

# его распознаванием:

BrowserMatch ^Mozilla/4 gzip-only-text/html

BrowserMatch ^Mozilla/4\.0[678] no-gzip

BrowserMatch Konqueror no-gzip

BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# указываем прокси-серверам передавать заголовок User-Agent для

# корректного распознавания сжатия

Header append Vary User-Agent

# запрещаем кэширование на уровне прокси-сервера для всех файлов,

# для которых у нас выставлено сжатие,

Header append Cache-Control: private

# включаем кэширование для всех файлов сроком на 10 лет

ExpiresActive On

ExpiresDefault "access plus 10 years"

# отключаем его для HTML-файлов

ExpiresActive Off

Конфигурация nginx 0.7+

Пример конфигурационного файла для одного виртуального сервера:

server {

#слушаем порт 80

listen 80;

#перечисляем через пробел имена этого сервера

server_name core.freewheel.ru:

#путь к корню сервера

root /my/path/to/core.freewheel.ru;

#пути к логам

access_log /my/path/to/core-access.log combined;

error_log /my/path/to/core-access.log info;

#подключаем шаблон настроек сервера, в нем самое интересное

include _servers_template;

#разрешаем себе посмотреть статус сервера

location = /nginx_status {

stub_status on;

access_log off;

allow 127.0.0.1;

deny all;

}

#включаем сжатие для тех браузеров, которые его понимают

gzip on;

#определяем минимальную версию протокола HTTP, для которой отдаем архивы

gzip_http_version 1.0;

#устанавливаем максимальный уровень сжатия

gzip_comp_level 9;

#разрешаем проксировать сжатые файлы

gzip_proxied any;

#и определяем типы файлов (все, которые хорошо сжимаются)

gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon;

}

А теперь собственно основной файл настроек (_servers_template), использующийся для всех виртуальных серверов в неизменном виде:

index index.php index.html;

location / {

# стили, скрипты и XML-файлы

location ~* ^.+\.(css|js|xml)$ {

# вот для этого и делались заранее архивированные .gz версии

# css и js файлов. Nginx не будет тратить время и сжимать их каждый раз

# заново, а просто отдаст уже готовые архивы, если браузер клиента может

# их принять

gzip_static on;

expires 1y;

}

# несуществующие файлы html и папки отправляем на бэкенд

if (!-e $request_filename ) {

rewrite ^/(.*)$ /index.php ;

}

# проксируем все запросы к PHP-файлам на FCGI бэкенд

location ~* \.php$ {

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

include _fastcgi_params;

}

# картинки

location ~* ^.+\.(bmp|gif|jpg|jpeg|ico|png|swf|tiff)$ {

expires 1y;

}

# файлы

location ~* ^.+\.(bz2|dmg|gz|gzip|rar|tar|zip)$ {

expires 1y;

}

# другие статические файлы

location ~* ^.+\.(pdf|txt)$ {

expires 1y;

}

}

Обычно nginx собирается без модуля статического сжатия, поэтому при его сборке надо указать опцию --with-http_gzip_static_module — без этого gzip_static не заработает, и серверу придется сжимать файлы каждый раз заново. Также надо иметь в виду, что указанная конфигурация приведена для версии 0.7+.

Настройка IIS

В IIS включить сжатие достаточно просто: необходимо в диспетчере служб IIS зайти в свойства элемента «Веб-узлы» и перейти во вкладку «Служба».

Плюсы такого включения сжатия:

простота;

поддержка сжатия IIS статических файлов;

поддержка кэширования сжатых файлов;

не требует написания кода.

Минусы включения поддержки сжатия на сервере IIS:

во всех случаях решает сервер, и вы не будете знать, что, когда и как сжимается;

глобальное включение: сжатие включается для всей службы разом и будет влиять на все узлы или виртуальные каталоги вашего сервера (по крайне мере, через gui отключить сжатие у конкретного узла нельзя);

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

8.4. Разбор полетов

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

vkontakte.ru

В Контакте ( http://vkontakte.ru/ ) является на данный момент (по числу просмотров страниц) наиболее посещаемым сайтом. Диаграмма загрузки внутренней страницы профиля выглядит примерно следующим образом:

Рис. 8.18. Результаты анализа загрузки внутренней страницы сайта vkontakte.ru

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

Двигаемся дальше: gzip. Для всех текстовых файлов (HTML, CSS, JavaScript) он включен. Это не может не радовать. Однако никакой минимизации для них не производилось. С точки зрения производительности это совсем не большая оплошность: при самой лучшей минимизации выиграть больше 5% от уже имеющегося сжатия крайне сложно. Для пользователей же это отразится в 10-50 мс загрузки.

Объединение файлов. После применения сжатия CSS- и JavaScript-файлы стали занимать 2-5 Кб, поэтому загружать их по отдельности особого смысла не имеет. Объединение наиболее используемых стилевых правил в основной файл (пусть даже размером в 15-20 Кб) позволило бы сократить время загрузки на 100 мс (в данном случае). Стоит также отметить, что для пользователей IE загружается дополнительный файл стилей (крайне маленький в размере), который, естественно, можно было бы включить в основной.

Пост-загрузка для JavaScript-компонентов. На странице уже используются данные методы — в частности, рекламные баннеры загружаются как раз через динамическое создание изображений в заранее определенных блоках шаблона страницы. Однако вынесение всей клиентской логики в загрузку по комбинированному событию window.onload позволило бы отрисовать страницу на экране на 300 мс быстрее (в данном случае это 40% от стадии предзагрузки). Хотя, возможно, это потребовало бы достаточно существенной переработки текущего функционирования отдельных частей портала.

Кэширование. На данный момент с этим все замечательно: выставляется как max-age для статических файлов, так и Last-Modified. Предполагается, что большинство пользователей заходят на vkontakte.ru постоянно, поэтому большая часть файлов берется браузером сразу из кэша. Именно поэтому наличие стилей и скриптов внутри HTML-файла сведено к минимуму: это позволяет уменьшить объем последнего при наличии в кэше всех необходимых файлов. Также стоит отметить, что в качестве внешнего сервера используется nginx.

Рис. 8.19. Заголовки ответа для статического файла с vkontakte.ru

На странице присутствует некоторое количество (5-10) небольших фоновых картинок, которые могли бы быть успешно объединены в CSS Sprites или даже добавлены в соответствующий CSS-файл. Однако данное действие не сильно спасло бы ситуацию — основная нагрузка приходится на пользовательские картинки. А почти все они расположены на различных хостах (на диаграмме загрузки присутствует несколько десятков хостов). Это хорошо для уменьшения времени ожидания ответа, но плохо с точки зрения DNS Lookup. В качестве дополнительного минуса можно назвать то, что средний размер картинки — 2 Кб.

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

В качестве возможного решения данной проблемы стоит рассматривать создание Image Map (или CSS Sprites) с наиболее часто используемыми изображениями для данной страницы. Для страницы пользователя — это список написавших на стене: он меняется относительно редко, а объединение иконок пользователей в группы по 5-7 (размер итогового файла 10-15 Кб) позволит несколько сократить время загрузки страницы. В общем случае (рассматривая параллельные загрузки) это будет DNS Lookup + время соединения. Хотя vkontakte.ru уже и так использует своего рода CDN (время соединения сведено к минимуму), выигрыш все равно составит порядка 200–300 мс даже для широкополосного доступа.

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

odnoklassniki.ru

Рис. 8.20. Результаты анализа загрузки внутренней страницы сайта odnoklassniki.ru

Давайте рассмотрим прямого конкурента vkontakte.ru — odnoklassniki.ru. Для этого сайта ситуация, очевидно, еще хуже. Во-первых, значительная часть декоративных картинок не внесена в число фоновых изображений, что заставляет IE старых версий опрашивать их в обычном порядке. Во-вторых, рекламные баннеры не вынесены в пост-загрузку и сильно мешаются в общем процессе отображения страницы (часть страницы с баннером «зависает» в ожидании ответа рекламного сервера). Обилие счетчиков статистики только усугубляет ситуацию.

Как с этим можно бороться? Естественно, что все файлы скриптов можно и нужно объединить в один, и его вынести в пост-загрузку. Фоновые картинки достаточно объединить в 2-3 файла, что позволит загружать иконки других пользователей (а именно они составляют наиболее значительную часть) быстрее.

Рис. 8.21. Результаты ответа для статического файла с odnoklassniki.ru

В остальном почти все меры уже приняты: текстовые файлы отдаются сжатыми, для статики устанавливается срок кэширования в далекое будущее. Однако, как видно из рис. 8.21, с кэшированием произошел небольшой перебор: наличие и ETag, и Last-Modified заголовка является избыточным. Для корректной проверки файла на существование новой версии достаточно только одного из них.

Естественно, что для odnoklassniki.ru проблема распределения различных изображений по нескольким хостам так же актуальна, как и для vkontakte.ru. И на данный момент она решается точно так же. Поскольку статические блоки с большим количеством изображений на странице практически отсутствуют, то более корректное решение указанной проблемы может и не существовать.

yandex.ru

Давайте вслед за самыми популярными социальными сетями рассмотрим наиболее посещаемые поисковые и почтовые порталы Рунета. Начнем с Яндекса.

Рис. 8.22. Результаты анализа загрузки главной страницы www.yandex.ru

Как можно видеть, эта страница уже сильно оптимизирована. При всем объеме информации и внутренней логики используется всего 19 запросов к серверу; общий объем передаваемых данных — 49 Кб. В качестве характерного шага оптимизации часто посещаемых главных страниц таких порталов можно назвать то, что CSS-файл внесен внутрь HTML и вся JavaScript-логика располагается там же (не учитывая, конечно, какие-то непостоянные явления, вроде блока авторизации или сезонной рекламы).

Естественно, что для текстовых файлов применяется сжатие, причем даже сам HTML-код минимизирован почти по максимуму: убраны переводы строк и лишние пробелы. В качестве спорного момента можно отметить отсутствие кэширования для главной страницы. Раньше его включали на 5 минут, чтобы уменьшить число повторных запросов. На данный момент (наверное, в связи с блоком почтовой авторизации) всякое кэширование отключено. Однако корректная настройка Last-Modified (в зависимости от переменных окружения, связанных с конкретным пользователем) могла бы уменьшить число передаваемых данных (сервер мог бы ответить статус-кодом 304 и не передавать всех данных).

Рис. 8.23. Результаты ответа для HTML-файла с yandex.ru

Во всем остальном соблюдены почти все рекомендации: наиболее часто используемые картинки объединены в CSS Sprites, при загрузке статических файлов задействуется несколько хостов (в том числе те, на которые не передаются cookie). Однако, как видно из диаграммы загрузки, на странице еще есть некоторое количество небольших изображений, которые также можно объединить в одно или даже внести в сам документ (для всех браузеров, кроме IE) в виде data:URI.

rambler.ru

Рис. 8.24. Результаты анализа загрузки главной страницы www.rambler.ru

В случае в Рамблером ситуация несколько другая: на главной странице портала представлено достаточно большое количество информации, в связи с чем число внешних объектов значительно больше — уже 46.

Естественно, для текстовых файлов уже включено сжатие. Но минимизации конечный HTML-файл не подвергнут — видимо, разработчики Рамблера заботятся о трафике своих пользователей не так тщательно.

CSS Sprites довольно активно используются на странице, но и тут не обошлось без очевидных промахов. Например, иконки для состояний погоды можно было с легкостью объединить в один файл, однако это не было сделано. Использование PNG-формата вместо GIF для фоновых изображений также способно уменьшить размер конечного файла. Применение же скрипта patch_script.js размером в 185 байтов (по сравнению с HTML в 20 Кб) крайне неосмотрительно.

Для загрузки большинства изображений (как хорошо видно из диаграммы загрузки) используется всего 2 хоста (rambler.ru и i.rl0.ru). Увеличение их числа до 4 позволило бы существенно ускорить процесс загрузки многочисленных картинок. Поскольку картинки занимают около 60% от общего времени, то добавление двух хостов для них позволило бы ускорить загрузку страницы на треть. Дополнительно: большинство JPEG-изображений сгенерированы не оптимальным образом, и их размер можно уменьшить на 20-30%.

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

mail.ru

Mail.ru является, пожалуй, наиболее крупным почтовым порталом в Рунете. Все остальные сервисы на нем появились именно благодаря почте и базе держателей почтовых адресов.

Рис. 8.25. Результаты анализа загрузки главной страницы www.mail.ru

Сам HTML-документ отдается через gzip, но для CSS- и JavaScript-файлов сжатие не применяется (что, естественно, плохо отражается на времени загрузки). На странице запрашивается 4 JavaScript-файла и 3 CSS. При этом JavaScript подключается в основном в head страницы. Это все крайне негативно влияет на скорость отображения страницы. Однако, как видно из рис. 8.26, кэширование для файлов стилей и скриптов включено при помощи Expires и Last-Modified. Это не может не радовать.

Рис. 8.26. Результаты ответа для статического файла с mail.ru

Фоновые картинки уже объединены в спрайты (хотя есть еще возможности для объединения), однако дополнительное уменьшение размера возможно за счет использования PNG. Также большинство JPEG-картинок можно существенно уменьшить в размере. Можно рассмотреть кэширование и объединение нескольких картинок (из блоков «Фото» или «Видео») в Image Map, чтобы уменьшить число запросов к серверу.

Для статических файлов используется всего 2 хоста (r1.mail.ru и img.mail.ru). Добавление еще двух (вместе с уже описанными методами уменьшения размера графики) способно ускорить загрузку примерно в два раза. В целом же у разработчиков mail.ru есть еще большой простор для творчества в области клиентской оптимизации.

rbc.ru

Давайте от рассмотрения крупных развлекательных порталов переместимся к конкретно новостным. Первым в этой среде можно рассмотреть сайт РИА «РосБизнесКонсалтинг».

Рис. 8.27. Результаты анализа загрузки главной страницы www.rbc.ru

Сразу бросается в глаза, что на странице используется 3 CSS-файла и 3 JavaScript-файла, которые можно объединить в один и сэкономить приличное время, не утомляя пользователя белым экраном. Также для текстовых файлов не включено никакое сжатие, что существенно увеличивает время их передачи (115 Кб HTML-кода ведь не мгновенно поступают).

Преобразование .gif в .png и устранение комментариев из JPEG-файлов способно сократить объем передаваемых данных еще примерно на 20% от 514 Кб, которые загружаются при открытии данной страницы (фактически объем самого HTML-файла). CSS Sprites в данном случае могут сократить общее число запросов как минимум на треть (хотя на этом сайте иконки для погоды уже «склеены» в один файл).

Естественно, добавление еще 3 хостов (к pics.rbc.ru) для выдачи картинок только повысит скорость загрузки (еще на 40-50%). С кэшированием, правда, здесь все отлично: кэш устанавливается на 3 часа, и есть заголовок Last-Modified, позволяющий отвечать 304 в том случае, если файл не изменился с момента последнего посещения.

В целом, за исключением явных недосмотров, сайт являет пример грамотного подхода к клиентской оптимизации.

lenta.ru

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

Рис. 8.28. Результаты анализа загрузки главной страницы lenta.ru

Здесь заметна забота о пользователях: все текстовые файлы отдаются сжатыми, картинки в новостях минимизированы, используется только один файл стилей и из скриптов — только внешние счетчики. Теперь о грустном (рис. 8.29).

Рис. 8.29. Результаты ответа для статического файла с lenta.ru

Файл стилей отдается без указаний для браузера сохранять его в кэше (Cache-Control и(ли) Expires), однако ETag дублирует функциональность Last-Modified. Это не есть хорошо. Для всех остальных статических файлов (изображений) заголовки настроены абсолютно корректно (хотя время кэша можно было увеличить до недели, например).

Поскольку для всех картинок используется только один хост (img.lenta.ru), то введение еще одного-двух хостов способно существенно (до 50%) ускорить загрузку главной страницы (в силу большого количества вызываемых изображений). Из дополнительных мер, которые хорошо было бы применить, но которые не дадут ощутимого прироста, стоит назвать CSS Sprites и добавление рекламы через «ненавязчивый» JavaScript.

Команду разработчиков можно только похвалить за достаточно ответственный подход к своему делу.

kommersant.ru

Рис. 8.30. Результаты анализа загрузки главной страницы kommersant.ru

Для сайта Издательского Дома «КоммерсантЪ» все не так радужно. Как видно из диаграммы загрузки, все счетчики загружаются в самую первую очередь, что существенно оттягивает появление содержания страницы на экране. Кроме того, почти все рекламные баннеры загружаются перед основными изображениями. В бочке дегтя есть и ложка меда: включено сжатие для HTML- и CSS-файлов. Но про JavaScript почему-то забыли (рис. 8.31):

Рис. 8.31. Результаты ответа для JavaScript-файла с kommersant.ru

Едем дальше. Как видно из рис. 8.31, кэширующие заголовки в норме, но есть избыточность в виде пары ETag / Last-Modified (которую можно устранить и сэкономить немного трафика и пользовательского времени). Минимизация для текстовых файлов не применяется, но в случае наличия сжатия это не настолько критично.

Изображения же существенно «раздуты» в размере. Перевод .gif в .png способен сэкономить до 50 Кб (при общем размере всех файлов более 800 Кб). CSS Sprites и добавление еще 3 хостов для изображений в статьях могут повлиять на скорость загрузки гораздо сильнее: ведь именно на картинки падает основная тяжесть. Здесь возможен выигрыш до 60% от текущего времени загрузки. Если добавить к этому отображение баннеров на стадии пост-загрузки, то есть возможность просто феноменально ускорить отображение сайта.

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

marketgid.ru

Давайте после развлекательных и новостных порталов перейдем ближе к «реальному» бизнесу и рассмотрим загрузку товарного каталога на примере MarketGid.

Рис. 8.32. Результаты анализа загрузки главной страницы marketgid.ru

На первый взгляд тут вообще все запущено: более 300 HTTP-запросов передают в браузер пользователя около 700 Кб данных. На второй взгляд тоже все не очень хорошо: сжатие включено только для HTML-файлов, стили и скрипты отдаются как есть. Всего 1 CSS-файл для «нормальных» браузеров компенсируется тремя для любой версии IE (а пользователей с таким браузером сейчас 60-70%). Хотя и вызывается всего 2 внешних JavaScript-файла.

Поскольку даже в сжатом виде HTML занимает около 70 Кб, то стоило бы обратить больше внимания на его структуру. Например, убрав лишние пробелы и переводы строк и включив на сервере максимальный уровень сжатия, можно уменьшить его размер на четверть. Если рассмотреть использование спецификации HTML 4.01 для формирования документа, то, скорее всего, файл можно «порезать» еще сильнее.

Хотя некоторые GIF-изображения можно перевести в .png формат и объединить в CSS Sprites, это не очень поможет делу: у нас на странице несколько сотен изображений размером 2-4 Кб, они формата .jpg и уже достаточно хорошо оптимизированы. Поскольку какая-то часть страницы все равно кэшируется для снижения нагрузки на сервер, то логично было бы объединить изображения в Image Map 15-20 Кб, ускорив их появление у пользователя в несколько раз.

Для загрузки статической информации на странице уже применяется несколько хостов, поэтому, скорее всего, увеличение их количества ни к чему не приведет.

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

habrahabr.ru

Хабрахабр, являясь одной из наиболее популярных социальных сетей в ИТ-сфере, позиционирует себя, в том числе, как достаточно «продвинутый» ресурс. Давайте посмотрим, насколько же он таковым является.

Рис. 8.33. Результаты анализа загрузки главной страницы habrahabr.ru

Использование 6 CSS- и 15 JavaScript-файлов (подключаемых в head страницы) сразу портит все впечатление. Загрузка сайта в самый первый раз (или при отключенном кэше) на небыстром соединении может быть похожа на настоящий кошмар: белый экран в браузере даже не пытается пропасть. Хорошей новостью будет то, что все текстовое содержимое архивируется. Замечательно, но файлы все же нужно объединять.

Далее, смотрим на загрузку картинок: в них большой простыней выделяется favicon-группа. Казалось бы, хорошая идея — выкачивать иконки компаний к себе на сервер и отдавать их пользователю намного быстрее. Однако в силу того, что получается очень много небольших объектов, разумнее было бы объединять их в Image Map — например, все, что выводятся на главной странице (кэшировать на 10 минут).

Кэширование на сайте уже настроено как должно: для социальной сети количество повторных запросов для просмотра внутренних страниц должно быть минимальным. Однако есть большое количество декоративных изображений, которые можно и нужно объединить в CSS Sprites. После объединения изображений стоит также добавить для них один и два дополнительных хоста — это ускорит их загрузку.

В качестве альтернативных методов есть возможность подключить JavaScript через «отложенную» загрузку и загружать рекламные баннеры только после отображения сайт-страницы.

Загрузка...