| Предисловие | 21 |
| |
| Для чего нужна эта книга? | 22 |
| Для кого предназначена эта книга? | 23 |
| Сделанные предположения | 23 |
| Как устроена эта книга | 24 |
Шрифты | 26 |
| Как с нами связаться | 27 |
| Другие книги и ресурсы | 27 |
Книги | 27 |
Веб-сайты, посвящённые производительности | 28 |
Группы новостей, имеющие отношение к производительности веб | 29 |
| Ограничение гарантий | 29 |
| Благодарности ко второму изданию | 30 |
| |
| Часть I. Предварительные сведения |
| |
| Глава 1. Быстрый и мёртвый | 32 |
| |
| Проверка браузера | 32 |
| Проверка сервера | 40 |
| Основные рекомендации | 46 |
| |
| Глава 2. Архитектура веб-сайта | 47 |
| |
| Компромиссы | 47 |
Сохранение информации и масштабируемость | 47 |
Дублирование и простота | 49 |
Синхронность и асинхронность | 50 |
Связь без логического соединения | 50 |
Планирование и разработка | 51 |
Процедурное и объектно-ориентированное программирование | 52 |
| Основы | 53 |
Браузер | 53 |
Система балансировки нагрузки | 54 |
Веб-сервер | 57 |
Связующие программы | 57 |
База данных | 58 |
| Пример архитектуры веб-сайта | 58 |
Один компьютер | 58 |
Стековая архитектура | 59 |
Уровни | 60 |
Linux на мейнфрейме | 60 |
Реальный масштаб времени | 60 |
Тенденции | 61 |
Программы, используемые на широко известных сайтах | 62 |
| Примеры конфигураций | 62 |
Низкая нагрузка | 62 |
Средняя нагрузка | 63 |
Большая нагрузка | 63 |
Какие сайты являются наиболее загруженными? | 64 |
| Основные рекомендации | 64 |
| |
| Глава 3. Планирование мощностей | 65 |
| |
| Займитесь подсчётами… | 65 |
| …но верьте своим глазам больше, чем цифрам | 66 |
| Вопросы, которые нужно себе задавать | 67 |
| Какая вам нужна пропускная способность? | 76 |
Время ожидания важнее пропускной способности | 77 |
О пропускной способности | 77 |
Оценка пропускной способности сети веб-сервера | 79 |
| Насколько быстрый сервер вам нужен? | 80 |
| Сколько памяти нужно серверу? | 81 |
Память для операционной системы | 82 |
Память для httpd | 83 |
Память для содержимого | 83 |
Память для CGI | 83 |
| Основные рекомендации | 84 |
| |
| Глава 4. Контроль производительности | 85 |
| |
| Параметры производительности | 85 |
| Время ожидания и пропускная способность | 85 |
Время ожидания для сети | 88 |
Измерение времени ожидания и пропускной способности сети | 89 |
| Коэффициент использования | 92 |
| Эффективность | 92 |
Использование сценариев интерпретатора | 93 |
Использование С | 94 |
Использование Perl | 96 |
| Контроль производительности сети с помощью Perl | 96 |
Отображение результатов с помощью gnuplot | 97 |
Пример сценария на Perl | 97 |
Компоненты | 102 |
| Автоматическая генерация сценариев для контроля с помощью sprocket | 103 |
| Использование реляционной базы данных для сохранения данных |
о производительности | 109 |
Помещение данных в базу | 110 |
Получение данных из базы | 110 |
| Контроль коэффициента использования с помощью rstat | 111 |
Сохранение данных rstat в реляционной БД | 114 |
Использование данных rstat | 115 |
Получение данных из БД в стандартный поток вывода | 115 |
Построение графиков данных, хранящихся в БД | 116 |
| Контроль статистики процессов | 119 |
Использование CGI для запуска программных средств | 120 |
Включение подробного анализа с помощью rstat | 120 |
Работа с Telnet в языке Perl | 121 |
Генерация графиков из результатов работы ps | 123 |
| Контроль прочих параметров | 127 |
| Контроль с помощью Java | 130 |
| Приборная панель на веб-странице | 133 |
| Внимание! Избыток контроля вреден для здоровья вашего сайта! | 134 |
| SNMP | 134 |
| RMON | 135 |
| ARM | 135 |
| Прочие ресурсы | 135 |
| Основные рекомендации | 136 |
| |
| Глава 5. Тестирование на нагрузку | 137 |
| |
| Подготовка к тестированию | 137 |
Опасайтесь переустановки часов | 138 |
Почему реальная производительность отличается от тестовой? | 139 |
| Средства тестирования нагрузки | 139 |
Написание собственных тестовых программ | 140 |
Проблемы с таймером | 141 |
| Тестирование на нагрузку при избыточном контроле | 143 |
| Синхронизация теста на нагрузку | 146 |
Хаотическое тестирование на нагрузку | 146 |
| Как остановить тестирование? | 146 |
| Создание нагрузки на сеть | 147 |
| Спецификации и эталонные тесты | 148 |
WebStone | 150 |
SPECweb99 | 151 |
ТРС-С и ТРС-D | 151 |
Тесты прокси-серверов | 152 |
Тесты производителей | 152 |
CaffeineMark | 152 |
Прочие ресурсы | 152 |
| Основные рекомендации | 152 |
| |
| Глава 6. Анализ производительности | 153 |
| |
| Поиск «узких мест» с помощью analysis.cgi | 153 |
| Подслушивание HTTP с помощью sprocket | 156 |
| Изучение соединений | 157 |
| Анализ файлов журналов | 157 |
Средний объём передачи | 159 |
Распределение размеров файлов | 162 |
| Хиты в секунду | 163 |
| Переменная нагрузка и длина очереди | 165 |
| Когда конкретно записываются хиты? | 166 |
| Кто ваш самый частый пользователь? | 167 |
| Который из процессов мой? | 168 |
| Кто работает с этим файлом? | 168 |
| Какие файлы используются моими процессами? | 169 |
| Что происходит при зависании БД? | 169 |
| Ещё немного советов | 170 |
| Основные рекомендации | 171 |
| |
| Глава 7. Надёжность | 172 |
| |
| Типичные отказы | 172 |
Переполнение диска | 172 |
У процесса закончились файловые дескрипторы | 173 |
Ошибки при работе с указателями на С | 173 |
Утечки памяти | 173 |
Блокировка потоков | 174 |
Блокировка ресурса завершившимся процессом | 175 |
Перегрузка сервера | 175 |
Система балансировки нагрузки не может обнаружить |
отказавший компьютер | 176 |
Перегружена подсеть | 176 |
Израсходованы терминалы | 176 |
В базе данных закончились указатели | 176 |
Плохой драйвер устройства | 177 |
Отказы оборудования | 177 |
Отказ питания | 177 |
Администратор перепутал сервер | 177 |
Ошибочное включение файла в шаблон | 178 |
Проблемы с разрешениями | 178 |
Ошибки в путях | 178 |
Проблемы с заплатами | 178 |
Каскадное распространение перегрузки | 179 |
Отказы из-за контроля | 179 |
Повторные обращения вызывают новые отказы | 179 |
Случайная блокировка важных таблиц | 179 |
Использование БД там, где можно обойтись файлами | 180 |
Программа не может подключиться к БД после отказа | 180 |
Программа не перезапускается после перезагрузки | 180 |
«Раздвоение личности» | 180 |
Брандмауэр блокирует важную службу | 180 |
Чтение данных с экрана не работает из-за того, что меняется дизайн | 181 |
Зависимости | 181 |
| Борьба с последствиями отказа | 181 |
| Основные рекомендации | 182 |
| |
| Глава 8. Безопасность | 183 |
| |
| HTTPS и SSL | 183 |
| Брандмауэры | 187 |
| Узлы-бастионы | 187 |
| Chroot | 188 |
| Основная рекомендация | 188 |
| |
| Глава 9. Разбор ситуаций | 189 |
| |
| Неограниченный рост таблицы | 189 |
| Обратный поиск в DNS замедляет работу с журналом | 190 |
| Перекрученный кабель | 192 |
| Рост пула базы данных ограничивает производительность | 195 |
| Основная рекомендация | 196 |
| |
| Глава 10. Принципы и схемы | 197 |
| |
| Принципы повышения производительности | 197 |
Иногда приходится проигрывать | 197 |
Измерение меняет объект | 197 |
Знания важнее всего | 198 |
«Бесплатных обедов» не бывает | 198 |
Доходы сокращаются | 199 |
Переносимость уменьшает производительность | 199 |
Абстрагирование уменьшает производительность | 200 |
Защищённость уменьшает производительность | 201 |
Память имеет иерархическую структуру | 201 |
Кэширование зависит от локальности ссылок | 202 |
Операции ввода-вывода всегда медленны | 202 |
Информация относительна | 203 |
Оборудование дёшево, программы дороги | 205 |
Целью оптимизации является одновременность выхода из строя |
компонентов | 205 |
Хорошее относительно | 206 |
Биты — это деньги | 206 |
Производительность Интернета падает нелинейно | 206 |
Глобальная оптимизация даёт наилучшие результаты | 207 |
Что произошло однажды, скоро произойдёт снова | 207 |
Правило 80/20 | 207 |
Люди часто важнее знаний | 207 |
| Схемы улучшения производительности | 208 |
Амортизация | 208 |
Кэширование | 208 |
Профилирование | 209 |
Параллельная обработка | 209 |
Используйте то, что знаете | 210 |
Простота | 210 |
| Основные рекомендации | 210 |
| |
| Часть II. Подробно об оптимизации |
| |
| Глава 11. Браузеры | 212 |
| |
| Как работают браузеры | 212 |
| Виды браузеров | 217 |
Netscape | 217 |
Internet Explorer | 217 |
Opera | 218 |
Neoplanet | 218 |
WebTV | 219 |
Cello | 219 |
Mosaic | 219 |
lynx | 219 |
Amaya | 220 |
Tango | 220 |
Идеальный браузер | 220 |
| Скорость браузера | 221 |
| Советы по настройке браузеров | 222 |
Общие рекомендации | 222 |
Советы для Internet Explorer | 227 |
Советы для Netscape | 227 |
| Прочие веб-клиенты | 228 |
| Gnutella и одноранговые сети | 229 |
| Основные рекомендации | 230 |
| |
| Глава 12. Операционная система клиента | 231 |
| |
| Microsoft Windows | 231 |
Устраните беспорядок в системе | 231 |
Специальные драйверы экрана | 232 |
Память и диски | 232 |
Системный монитор | 233 |
Сетевые утилиты | 233 |
MTU | 234 |
| Macintosh | 234 |
Эмуляция 68К | 234 |
Сеть | 235 |
Память и диск | 235 |
Расширения | 236 |
| Unix | 236 |
| Основные рекомендации | 238 |
| |
| Глава 13. Аппаратное обеспечение клиента | 239 |
| |
| Процессор | 239 |
| ОЗУ | 242 |
| Кэш | 243 |
| Шина | 243 |
| Диск | 244 |
IDE | 244 |
SCSI | 245 |
Фрагментация | 245 |
| Видео | 245 |
ММХ | 246 |
Цвета и разрешение | 246 |
Драйверы | 247 |
3D и видеоклипы | 247 |
Тесты для видеоадаптеров | 247 |
| Ввод-вывод | 247 |
UART | 248 |
Аппаратное сжатие может приводить к переполнениям | 249 |
| BIOS | 249 |
Основные рекомендации | 250 |
| |
| Глава 14. Линии связи и оконечные устройства | 251 |
| |
| Пересылка и время ожидания | 252 |
| Модем — выезд на информационную магистраль | 252 |
Время ожидания и пропускная способность от модема к модему | 253 |
Синхронизация | 254 |
Аппаратное сжатие | 254 |
Коррекция ошибок | 255 |
Качество линии | 255 |
Внутренние модемы быстрее | 256 |
Переполнение буферов UART | 256 |
Команды AT и время набора номера | 257 |
Объединение каналов | 257 |
| ISDN | 257 |
Кабельные модемы | 259 |
| xDSL | 259 |
| Ещё более скоростные линии | 260 |
56К, Т1 и ТЗ | 260 |
Frame Relay | 261 |
ATM | 261 |
Спутники | 262 |
| Интрасети | 262 |
Сегментирование | 262 |
Оборудование для сегментирования | 263 |
Ethernet | 265 |
Перехват пакетов | 267 |
Буферы сетевых адаптеров | 269 |
Быстрый Ethernet | 270 |
Коммутируемый Ethernet | 270 |
Кабели Ethernet | 271 |
Шум | 271 |
Средства моделирования сетей | 272 |
| Интернет | 272 |
В обход Интернета | 274 |
Точки доступа к сети | 274 |
Провайдеры | 276 |
Выбор провайдера | 278 |
Дублирование | 279 |
Маршрутизаторы | 279 |
Кто виноват? | 280 |
Будущее Интернета | 281 |
| ПТТ | 281 |
| Основные рекомендации | 282 |
| |
| Глава 15. Сетевые протоколы | 283 |
| |
| Власть и протоколы | 283 |
| Факторы, влияющие на производительность сетевых протоколов | 285 |
Пакеты, кадры и ячейки переменного и фиксированного размеров | 285 |
Совмещённая отправка | 285 |
Конвейер и подтверждение отдельных пакетов | 286 |
Односторонние и двусторонние протоколы | 286 |
Ошибки | 286 |
Количество прыжков | 286 |
Уровни | 286 |
| Протоколы веб | 287 |
ARP | 287 |
РРР | 287 |
Протоколы маршрутизации | 288 |
Протокол Интернета | 288 |
TCP | 292 |
Т/TСР | 302 |
UDP | 303 |
HTTP | 305 |
FTP | 315 |
NNTP | 316 |
CORBA | 316 |
X | 317 |
| Основные рекомендации | 317 |
| |
| Глава 16. Аппаратное обеспечение сервера | 318 |
| |
| Коробка с проводом | 318 |
| Хорошая подсистема ввода-вывода | 319 |
Несколько шин | 319 |
Быстрые диски | 319 |
Много памяти | 320 |
| Масштабируемость | 320 |
| Сетевой адаптер | 320 |
| Шина | 322 |
| Оперативная память | 323 |
Характеристики ОЗУ | 323 |
| Процессор | 324 |
Архитектура процессора | 325 |
Многопроцессорные компьютеры | 328 |
Тестирование масштабируемости Sun SMP | 329 |
| Жёсткий диск | 342 |
Архитектура и параметры дисков | 342 |
IDE | 344 |
EIDE | 344 |
SCSI | 345 |
Fibre Channel | 345 |
RAID | 346 |
Производительность типичных дисков | 346 |
Фрагментация | 347 |
Активность дисков и идентификаторы процессов | 348 |
| Основные рекомендации | 348 |
| |
| Глава 17. Операционная система сервера | 349 |
| |
| Unix и рождение Сети | 349 |
| Версии Unix | 350 |
Solaris | 351 |
AIX | 352 |
Digital Unix | 352 |
Linux | 352 |
Irix | 353 |
BSD | 353 |
Mach OS | 353 |
| Устройство Unix | 353 |
Системные и библиотечные вызовы | 353 |
Процессы и ядро | 354 |
Планирование | 354 |
Контекст ядра | 355 |
Unix и httpd | 356 |
Уменьшение нагрузки на операционную систему | 358 |
Создание процессов | 359 |
Адресное пространство | 360 |
Копирование областей памяти | 362 |
Освобождение памяти | 362 |
Файловая система | 364 |
Оконный интерфейс | 372 |
Версии и заплаты | 372 |
Настраиваемые параметры операционных систем | 373 |
Количество дескрипторов файлов | 373 |
Частота очистки буферов файловой системы | 376 |
| Средства контроля Unix | 377 |
ps | 377 |
perfbar | 378 |
perfmeter | 378 |
perfmon | 379 |
rstat | 380 |
rup | 380 |
hstat | 380 |
top | 380 |
xload | 381 |
Трассировщики системных вызовов | 381 |
Программы прослушивания сети | 383 |
netstat | 383 |
vmstat | 384 |
sar | 384 |
| Сколько соединений может обслужить мой веб-сервер? | 385 |
| Сколько процессов может одновременно выполняться на моём сервере? | 386 |
| Насколько быстро может мой сервер породить новый процесс? | 387 |
| Unix и Windows NT в качестве ОС для веб-серверов | 388 |
Достоинства и недостатки NT | 388 |
Достоинства и недостатки Unix | 389 |
| Проект Exokernel | 390 |
| Основные рекомендации | 390 |
| |
| Глава 18. Программное обеспечение сервера | 391 |
| |
| Эволюция веб-серверов | 391 |
Серверы, порождавшиеся демоном inetd | 391 |
Серверы, порождающие процессы | 392 |
Многопоточные серверы | 393 |
Серверы с постоянными соединениями | 393 |
| Системные вызовы веб-сервера | 393 |
| Как происходит сбой сервера | 395 |
Утечки памяти | 397 |
| Настройка Apache и Netscape | 397 |
Короткие пути | 397 |
Не преобразуйте время | 397 |
Буферизуйте запись в журнал | 397 |
Настройка Apache | 398 |
Настройка Netscape | 402 |
Прочие серверы | 407 |
| Недостающие функции | 409 |
| Прокси-серверы | 409 |
| Иерархическое кэширование | 410 |
| Основные рекомендации | 411 |
| |
| Глава 19. Содержимое | 412 |
| |
| Важен размер | 412 |
| Лучше не бывает | 413 |
| Кэширование и отличия | 413 |
| HTML и сжатие | 413 |
gzip | 414 |
| Советы HTML-разработчикам | 415 |
Полегче на сервере! | 415 |
Полегче в сети! | 416 |
Полегче с браузером! | 417 |
Полегче с пользователем | 418 |
Берегитесь предвзятых HTML-редакторов | 419 |
Идите в ногу с миром | 419 |
Используйте средства проверки HTML | 419 |
Объектная модель документа | 420 |
Графика | 420 |
Анимация | 422 |
VRML | 422 |
Аудио | 422 |
Видео | 423 |
| Основные рекомендации | 424 |
| |
| Глава 20. Специализированные приложения | 425 |
| |
| Программисты | 425 |
| CGI-программы | 425 |
| Внутреннее устройство CGI и вопросы производительности | 426 |
| Основные рекомендации | 428 |
Бесконечные циклы | 428 |
Неудержимо растущие CGI-программы | 429 |
Защита от зацикливания CGI-программ | 430 |
Не заставляйте клиента ждать | 431 |
Переложите обработку на браузер | 432 |
Файлы cookie | 434 |
Java | 434 |
Обрабатывайте запросы заранее и кэшируйте результаты | 435 |
| Короткая — значит красивая | 438 |
Вопросы масштабирования | 438 |
Разделяйте большие формы на несколько маленьких | 438 |
Поиск в DNS на сервере | 439 |
Отладка и оптимизация | 439 |
| Оптимизация CGI | 439 |
Сценарии интерпретатора | 439 |
Perl | 440 |
С | 442 |
| Демонизация | 444 |
| Производительность при обращении к БД | 445 |
| Ведение журналов | 445 |
| NSAPI и lSAPI | 446 |
| Объектная модель документа | 446 |
| JSP, ASP, PHP | 446 |
| Основные рекомендации | 447 |
| |
| Глава 21. Java | 448 |
| |
| Язык Java никогда не будет достаточно быстрым для пользовательских |
интерфейсов | 448 |
| Java достаточно быстр для серверных приложений | 449 |
| Внутренние проблемы с производительностью, присущие Java | 449 |
Проверка границ массивов | 449 |
Блокирующий сетевой ввод-вывод | 450 |
Интерпретация байт-кода | 450 |
Верификация байт-кода | 451 |
Динамическая привязка методов | 451 |
Сбор мусора | 451 |
Косвенная адресация | 452 |
Интернационализация и локализация | 452 |
Объектная ориентированность | 452 |
Стековая ориентация | 453 |
Синхронизация | 453 |
Многопоточное программирование | 453 |
| Советы программистам | 455 |
Используйте хорошие алгоритмы | 455 |
Делайте цепочки наследования короткими | 455 |
Используйте стековые переменные | 456 |
Объединяйте классы | 456 |
Используйте библиотеки Java | 457 |
Не опрашивайте | 457 |
«Финализируйте» методы | 457 |
Создавайте поменьше объектов | 457 |
Опасайтесь утечек объектов | 458 |
Попробуйте не пользоваться методами для работы с переменными | 458 |
Используйте сложные операторы | 458 |
Используйте шаг типа int | 458 |
Следите за скоростью доступа к различным переменным | 459 |
Локальные переменные быстрее, чем переменные класса | 459 |
Переменные класса быстрее, чем массивы | 459 |
Используйте собственные методы | 460 |
Используйте тайм-ауты сетевой подсистемы | 460 |
Буферизуйте ввод-вывод | 460 |
Используйте сокеты вместо URL | 460 |
Используйте UDP | 460 |
Используйте потоки | 461 |
Используйте notify | 462 |
Используйте синхронизацию как можно реже | 462 |
Не помещайте синхронизируемые методы внутрь циклов | 463 |
Следите за родительским потоком | 463 |
Обратный отсчёт бывает быстрее прямого | 463 |
Уменьшайте количество строк | 463 |
Используйте строчные буферы или массивы | 463 |
Берегитесь медленных шрифтов | 464 |
Упрощайте метод Paint | 464 |
Двойная буферизация обеспечит плавность анимации | 464 |
Пусть система отлавливает ошибки за вас | 464 |
Не преобразуете даты и время | 465 |
Берегитесь RMI, EJB и CORBA | 466 |
Компиляторы | 466 |
Оптимизация | 467 |
Профилируйте свой код | 467 |
JVMPI | 468 |
Декомпиляторы | 468 |
Средства профилирования на уровне операционной системы | 469 |
JIT-компиляторы | 469 |
Статические компиляторы | 470 |
Виртуальные машины | 471 |
| Параметры времени выполнения | 472 |
-verbosegc | 472 |
-noverify | 472 |
-Xmsn и -Xmxn | 472 |
Сделайте Рай побольше | 472 |
-train | 473 |
Используйте собственные потоки | 473 |
Используйте архивы .jar | 473 |
Подключаемый модуль Java | 473 |
-start_java | 474 |
Java-процессоры | 474 |
| Тесты для Java | 474 |
Недостатки тестов | 475 |
| Веб-сайты, где размещены сведения о производительности Java | 475 |
| Основные рекомендации | 475 |
| |
| Глава 22. Базы данных | 476 |
| |
| Нужна ли вам реляционная база даных? | 477 |
| Как узнать, что вам нужна база данных? | 477 |
| Альтернативы | 477 |
| Повышение производительности | 478 |
Подготовленные операторы и связанные переменные | 478 |
Денормализуйте таблицы | 479 |
Не создавайте курсоры в циклах | 479 |
Прямые соединения | 479 |
Базы данных в основной памяти | 479 |
Многоярусные системы | 479 |
Конфигурация пула соединений | 480 |
Запросы | 480 |
Индексы | 481 |
Блокировка на уровне строк | 481 |
Объединение веб-сервера и базы данных | 481 |
Сколько соединений может обслужить ваша база данных? | 482 |
Когда база данных перегружена | 483 |
Анализ | 483 |
| Основные рекомендации | 484 |
| |
| Приложение. Обзор продуктов, предназначенных |
для оптимизации веб-сайта | 485 |
| |
| Недостатки коммерческих средств | 485 |
| Средства контроля | 486 |
| Средства создания нагрузки | 490 |
| Упреждающие загрузчики | 491 |
| Оптимизаторы сетей | 492 |
Оптимизаторы MTU | 492 |
Optimal Application Expert | 492 |
| Контроль трафика на уровне IP | 492 |
| Системы сжатия содержимого | 494 |
| Гибриды средств разработки и баз данных | 495 |
| Профилировщики и оптимизаторы Java | 496 |
Службы кэширования | 496 |
| Профессиональные услуги | 497 |
| Средства балансировки нагрузки | 497 |
| Средства моделирования | 499 |
| |
| Алфавитный указатель | 500 |