УрокПроизводительность сайта на Drupal. Анализ серверной части.

Немного воды

Что делать, если сайт дохнет прямо на глазах? С чего начать, если вам подсунули полуживой проект с просьбой поднять его на ноги? Ответ выглядит немного по-капитански: анализ. Вам надо понять, где именно закралась проблема в производительности, которая мешает быстрой работе сайта. Сразу хочу сказать, что в этой статье я буду принимать на веру, что вы выбрали правильный хостинг, и проблема заключается не в нём. Безусловно, многие проблемы с производительностью на сервере можно решить докупив ещё железа, однако не каждый заказчик готов платить за это (хотя по подсчётам, докупить железа обойдётся гораздо дешевле, чем тратиться на специалиста по производительности, но кому это объяснишь ;)). Однако если же косяк с производительностью серьёзный - то он может съесть ресурсы даже докупленного железа, и тогда на вас очень обидятся. А если проблема окажется в клиентской части сайта - то хоть дата-центры скупайте, а у клиентов сайты будут тормозить.

Вступление

Сайт разделяется на 2 части - клиентская и серверная. К клиентской части относится всё, что скачивает браузер клиента (js, css, изображения, html). К серверной - всё, что от клиента спрятано (в основном это php код, включающий запросы к базе данных).

Первым делом надо посмотреть где тормозит сайт - на клиентской или серверной его части. В этом мне помогает Firebug (плагин Firefox). Открываем его на вкладке СЕТЬ и перезагружаем страницу.

performance_1.png

На первой строчке вы увидите время, которое потратил браузер на ожидание ответа от сервера (3,97 секунд - это непозволительно огромное время ожидания ответа от сервера). За это время поизошло следующее:

  • Браузер послал запрос к серверу на получение страницы
  • Друпал произвёл полный бутстрап
  • На серверной стороне выполнились все запросы к базе данных, необходимые для получения страницы
  • Был отрендерен весь контент, полученный из базы данных
  • Браузер получил ответ от сервера в виде сформированного html кода

Анализ серверной части сайта

Исходя из скриншоты видно, что проблема медленной загрузки страницы находится где-то на сервере. Это значит, что у нас либо тяжёлые запросы к базе данных, либо плохо написанный код. Для дальнейшего анализа необходимо поставить модуль devel. Из коробки он умеет отслеживать запросы к базе данных. На странице /admin/config/development/devel включите отслеживание запросов к базе данных:

performance_2.png

На скриншоте внизу располагается секция XHProf - о ней мы обязательно поговорим чуть позже.

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

performance_3_0.png

На скриншоте видно, что пару запросов несколько превышают желаемый лимит времени на запрос в 5 милисекунд. Однако чётко видно, что все запросы выполнились за 196 милисекунд (0,196 секунд), а это вполне неплохо => следовательно, проблема не в запросах. Если бы проблема была в них, можно было бы воспользоваться дополнительными опциями (пункт 3):

  • P - Placeholders, показывает запрос с заменителями переменных (как они есть на скриншоте)
  • A - Arguments, показывает аргументы запроса вместо placeholder'ов
  • E - Explain

Также на скриншоте можно заметить (пункт 2), что в какой-то момент PHP потребовалось 189 мб оперативки - а вот это уже много. Теперь было бы неплохо пробежаться по функциям и посмотреть в какой момент потребовалось столько памяти. С этим нам может помочь расширение XHProf (профилирование PHP). Примечательно, что поставить его можно только на *nix системы. Его установка (если самостоятельно):

pecl download xhprof-0.9.2
tar -xvf xhprof-0.9.2.tar.gz
cd xhprof-0.9.2/extension
phpize
./configure
make
make install

Дальше включите расширение в php.ini:

extension=xhprof.so
xhprof.output_dir=/var/log/xhprof;

Если сайт находится на хостинге - просто попросите хостеров включить XHProf :)

Следующим этапом вам надо создать отдельный домен для этого расширения. Например, локально я обычно называю его dev.xhprof (хотя можно и blabla.biz). Далее в директорию с доменом копируйте папки xhprof_html и xhprof_lib из файлов расширения. После этого перейдите на страницу с настройками devel'a и включите профилирование:

performance_4.png

Этот скриншот сделан с рабочего хостинга.

  • XHProf directory - путь к корню сайта в файловой системе сервера
  • XHProf URL - урл сайта, по которому доступна папка xhprof_html

Теперь на страницах сайта в строке с общей информацией devel'a прявилась ссылка на профилирование PHP:

performance_5.png

После нажатия на ссылку перед вами развернётся таблица с вызванными функциями, количеством времени, памяти и процессорного времени, затраченого на их выполнение:

performance_6.png

Сокращения:

  • Incl[usive] - ресурсы, потраченные на выполнение фунцкии со всеми функциями, вызванными из неё
  • Excl[usive] - ресурсы, потраченные на выполнение непосредственно данной функции

После нажатия в таблице на Excl. Wall Time (microsec) данные отсортируются по убыванию, показав мне функцию, которая выполнялась дольше всего:

performance_7.png

Как вы видите, дольше всего выполнялась фунцкия path_breadcrumbs_page_alter() - на её выполнение было потрачено 4,3 секунды - просто непозволительно долго. Нажимаем на название этой функции и смотрим, что же в ней ест столько времени и памяти:

performance_8.png

Очевидно, что пакостит функция count(), которая вызывается 2 миллиона раз и потратив на себя кучу времени. А array_fill() на 2млн элементов съел около 256 миллионов байт памяти (~244 mb). Открываем код функции path_breadcrumbs_page_alter() и смотрим:

function path_breadcrumbs_page_alter(&$page) {
 
  $a = array_fill(0, 2000000, 'пиу');
  for ($i = 0; $i < count($a); $i++) {
    // Мне очень стыдно ...
  }
 
  // Остальной код.
}

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

P.S. В следующей статье я расскажу о том, как проанализировать производительность и ускорить клиентскую часть сайта.

Комментарии

Аватар пользователя Kuzmich
Kuzmich написал:

Отличная статья. Даже не думал, что Firebag может и такое делать, обычно проверял скорость со сторонних ресурсов.

26.05.2012 20:59
Аватар пользователя Spleshka
Spleshka написал:

Вы будете удивлены, когда узнаете, что он ещё умеет. Дождитесь статьи по анализу клиентской части ;)

27.05.2012 14:40
Аватар пользователя max_d
max_d написал:

статья хороша, но жаль, что лишь анализом ограничились. применение apc, xcache, memcache, varnish, boost было бы тоже интересно проанализировать. к примеру, на семерки от включения xcache вообще не заметил толку, а с включением apc выделенных 256 мб для php становится сразу мало.

26.05.2012 22:08
Аватар пользователя Spleshka
Spleshka написал:

Об этом чуть позже напишу. Я хочу несколько статей посвятить кодерам для поиска утечек производительности. А о настройке сервера потом расскажу.

27.05.2012 14:41
Аватар пользователя max_d
max_d написал:

ок. ждем-с

27.05.2012 21:22
Аватар пользователя x.mik3l
x.mik3l написал:

Спасибо автору за статью : ) Было очень интересно почитать и с большим интересом ждем продолжения :) поскорее бы только... )

28.05.2012 13:55
Аватар пользователя BerdArt
BerdArt написал:

Отличная статья, однозначно в закладки :) must read! жду продолжения

28.05.2012 22:24
Аватар пользователя drup.by
drup.by написал:

"Примечательно, что поставить его можно только на *nix системы."

у меня на windows установлен и нормально работает .

30.05.2012 00:21
Аватар пользователя Spleshka
Spleshka написал:

А вот это уже интересно. Где-то читал, что только под *nix ставиться. Но раз работает - не вижу повода сомневаться в этом :)

31.05.2012 03:40
Аватар пользователя Гость
Гость написал:

я подключал по инструкции из этой статьи
только настройки подключения к базе данных в /xhprof_lib/config.php пришлось прописать напрямую в /xhprof_lib/utils/xhprof_runs.php

31.05.2012 05:35
Аватар пользователя sight
sight написал:

Подскажите почему может падать Mysql

PDOException: SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111) in lock_may_be_available() (line 167 of /var/www/includes/lock.inc).

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

02.06.2012 05:13
Аватар пользователя Spleshka
Spleshka написал:

Смотрите настройки в settings.php

02.06.2012 12:47
Аватар пользователя sight
sight написал:

Скажите вы системные .css Отключали хуками ? и еще такой вопрос почему у вас такие длинные названия файлов css и как то они не отсортированы )

02.06.2012 22:10
Аватар пользователя ice
ice написал:

О каких системных css речь ?

Названия большие из-за того что все файлы css объединяются - это оптимизация .

/admin/config/development/performance

03.06.2012 15:17
Аватар пользователя sight
sight написал:

Вот нашел способ, вставлять в template.php

function main_css_alter(&$css) {
unset($css[drupal_get_path('module','system').'/system.messages.css']);
unset($css[drupal_get_path('module','system').'/system.theme.css']);
}

03.06.2012 22:22
Аватар пользователя ice
ice написал:

Не знаю насколько правильно так делать .

Обычно это делают с помощью reset css .

Есть весьма не плохие стартовые темы , в которых это все есть .

В качестве примера могу посоветовать framework

04.06.2012 07:14
Аватар пользователя Семен Семеныч Горбунков
Семен Семеныч Г... написал:

Спасибо! Одна из немногих стоящих статей по оптимизации Drupal.

05.06.2012 14:34
Аватар пользователя vel-demon
vel-demon написал:

Благодарю за статью! Очень полезная.

17.02.2013 13:55
Аватар пользователя Эд
Эд написал:

Спасибо, отличный полезный информационный клад.

27.02.2013 03:17
Аватар пользователя Гость
Гость написал:

желаемый лимит времени на запрос в 5 милисекунд
========================================

а как понять - какой желаемый?

Следующая статья будет?

31.03.2013 11:15
Аватар пользователя Дмитрий
Дмитрий написал:

Здравствуйте, а если у меня вот такой результат

30.04.2013 13:38
Аватар пользователя Spleshka
Spleshka написал:

У вас проблема с базой данных. Тут много вариантов - плохие диски, плохо настроен mysql, и так далее. Если при минимальной нагрузке такие результаты - советую сменить хостера.

30.04.2013 20:16
Аватар пользователя Дмитрий
Дмитрий написал:

Спасибо, займусь переносом

01.05.2013 11:58
Аватар пользователя Роман
Роман написал:

Скажите пожалуйста, а под какой линукс Вы написали установку XHProf ?

У меня под CentOS 6 почему-то не получается.

Вроде бы, всё устанавливается, но вот сервис не запускается.

24.07.2013 21:52
Аватар пользователя kirminator2
kirminator2 написал:

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

08.01.2014 01:07
Аватар пользователя lordius
lordius написал:

Здравствуйте. У меня проблема скорости сайта в основном с запросами в вюшках. Профилирование подтвердило причину. Решил я пока эту проблему для нужных запросов поставив для полей nid и count индексы в мускуле. Насколько ли опрадавно даное решение и не будут ли потом изза этого проблемы?

19.03.2014 16:32
Аватар пользователя pavel
pavel написал:

Скажите, а что обозначает receiving, точнее что означает понятно, отчего этот параметр зависит. У меня на сайте waiting до 2 сек, а receiving примерно столько же. Посмотрел другие Друпал сайта, у них нап передачу совсем мало тратится времени?

14.10.2014 15:48
Аватар пользователя Spleshka
Spleshka написал:

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

16.10.2014 14:41
Аватар пользователя Геннадий
Геннадий написал:

"После нахождения косяка в производительности устраняем её...".
Можете ли более подробно описать, что было сделано? Что можно менять? (дополнить статью для непрофессионалов)

16.12.2014 21:58
Аватар пользователя tarasikarius
tarasikarius написал:

Не могу найти статью по анализу клиентсой части(

02.04.2015 10:35
Аватар пользователя Максим
Максим написал:

Добрый день,

Подскажите в чем может быть беда. При каждой перезагрузке странице происходит Update кеша.
http://joxi.ru/8235xENHb6garO (Для анонимов все ок, работает буст).
С кешем работаю не долго, установлен entity_cache.
Подскажите куда смотреть, как лучше дальше отдебажить сам запрос, почему он не сохраняет кеш, а постоянно его перезаписывает?

16.05.2015 00:04

Комментировать

                                                           
88888888888 888888888888 88 a8P 888b 88
88 88 88 ,88' 8888b 88
88 88 88 ,88" 88 `8b 88
88aaaaa 88 88,d88' 88 `8b 88
88""""" 88 8888"88, 88 `8b 88
88 88 88P Y8b 88 `8b 88
88 88 88 "88, 88 `8888
88888888888 88 88 Y8b 88 `888

Enter the code depicted in ASCII art style.