четверг, 17 апреля 2025 г.

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

Сегодня мы посмотрим на opensource-решение от компании Facebook – XHProf. Исходники были открыты в 2009-м году, правда с тех пор проект практически не развивается.
Профайлер позволяет произвести декомпозицию работы приложения до вызовов отдельных методов со сбором статистики по времени их отработки и использованию системных ресурсов. То есть если проблема в каком-то участке кода присутствует, то мы её найдем. Или хотя бы локализуем с определённой точностью.
То, что я напишу в этой статейке, будет иметь и общую информацию, но в большой степени всё-таки будет касаться частного случая – профилирования приложения, работающего в php-fpm, стоящего за nginx'ом. И всё это под Ubuntu 10.04.
Установка XHProf
Если речь идёт об Ubuntu (а моя речь именно о ней), то самым простым способом поставить XHProf будет PPA от Brian Mercer. Он же не так давно помог нам поставить и сам php-fpm на Ubuntu 10.04.
1.sudo add-apt-repository ppa:brianmercer/php5-xhprof
2.sudo apt-get update
3.sudo apt-get install php5-xhprof
4.sudo /etc/init.d/php5-fpm restart
5.php -m | grep xhprof
Последняя команда покажет нам наличие модуля xhprof в списке модулей PHP. Если он есть, то всё ок.
Если речь идёт не про Ubuntu (впрочем, для неё это тоже справедливо), то можно поставить XHProf из PECL или собрать вручную.
Установка из PECL:
pecl install xhprof-0.9.2
Установка вручную:
2.tar -xzvf xhprof-0.9.2.tgz
3.cd xhprof-0.9.2
4.phpize
5../configure --with-php-config=/usr/bin/php-config
6.make && make test && make install
И при ручной уствноке надо в php.ini добавить расширение:
1.extension=xhprof.so
2.xhprof.output_dir=/tmp
Установка graphviz

Для создания наглядных симпатичных диаграмм, визуализирующих цепочки вызовов функций в процессе работы приложения, на понадобится пакет graphviz. В Ubuntu он есть в репозиториях:
sudo apt-get install graphviz
Настройка XHProf
Для профилирования надо включить в приложение библиотеки из поставки xhprof и вызвать функцию xhprof_enable. Так как профилировать обычно нужно не все запросы, а выборочные, то можно сделать условие по наличию в заголовках запроса cookie определённого вида. В разных примерах в других публикациях обычно используется cookie xhprof. Самый простой способ добавить нужный код – это воспользоваться директивами auto_prepend_file и auto_append_file в php.ini.
Создадим файл /usr/share/php5-xhprof/header.php:
01.<?php
02.if(isset($_COOKIE['xhprof'])){
03.    if (extension_loaded('xhprof')) {
04.        $utils_path = "/usr/share/php5-xhprof/xhprof_lib/utils/";
05.        include_once $utils_path.'xhprof_lib.php';
06.        include_once $utils_path.'xhprof_runs.php';
07.        xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
08.    }
09.}
10.?>
Создадим файл footer.php:
01.<?php
02.if(isset($_COOKIE['xhprof'])){
03.    if (extension_loaded('xhprof')) {
04.        $profiler_namespace = 'someapp';
05.        $xhprof_data = xhprof_disable();
06.        $xhprof_runs = new XHProfRuns_Default();
07.        $run_id = $xhprof_runs->save_run($xhprof_data, $profiler_namespace);
08.        $profiler_url = sprintf('http://mysite:81/index.php?run=%s&source=%s', $run_id, $profiler_namespace);
09.        echo '<a href="'.$profiler_url.'">XHProf</a>';
10.    }
11.}
12.?>
Этот кусок кода, который будет отрабатывать в конце обработки запроса, сохранит собранные данные и добавит в конце ссылку на страницу профайлера. URL, само собой, надо поправить на тот, который приведёт нас на нужный виртуал хост. Об этом чуть позже.
Чтобы эти сниппеты срабатывали в нужные нам моменты, надо добавить в php.ini (в моём случае это /etc/php5/fpm/php.ini) строки:
1.auto_prepend_file = /usr/share/php5-xhprof/header.php
2.auto_append_file = /usr/share/php5-xhprof/footer.php
Само собой, можно вставлять соответствующие куски прямо в код страницы, чтобы профайлить не всё приложение целиком, а только какую-то его часть.
Настройка nginx
Для просмотра результатов профилирования в читабельном (и смотрибельном) виде, нужно настроить nginx. Я для этих целей сделал отдельный virtual-host, и это, само собой, не единственное возможное решение.
01.server {
02.        listen   81;
03.        server_name  mysite;
04.        root   /usr/share/php5-xhprof/xhprof_html;
05.        access_log  /var/log/nginx/xhprof.access.log;
06.        location ~ \..*/.*\.php$ {
07.                return 403;
08.        }
09.        location / {
10.                index index.php;
11.        }
12.        location ~ \.php$ {
13.                fastcgi_pass   unix:/tmp/phpfpm.sock;
14.                fastcgi_index  index.php;
15.                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
16.                include        /etc/nginx/fastcgi_params;
17.        }
18.}
Проверяем
Для установки cookie xhprof можно воспользовать плагином для Firefox – Cookies  Manager +. С помощью этого инструмента создаём новую куку, у которой в имени указываем xhprof, в содержимом – что угодно, а в узле – наш FQDN, с которым мы ходим на сайт.
После этого заходим на сайт и видим внизу страницы ссылку на профайл.
Если последнее утверждение истинно, то:
Вуаля!

Автоматизация
Бывают ситуации, когда приложение работает нормально, а проблемы начинаются в определеное время или вообще бессистемно. И хочется нам иметь результаты профилирования в исторической, так сказать, перспективе. Чтобы можно было посмотреть, как работало приложение, скажем, вчера в десять вечера.
Для этого можно пошаманить с header.php и footer.php, придумав хитрые условия. Например, рандомный запуск профайлера для каждого сотого запроса.
header.php:
1.if (rand(1, 100) == 1) {
2.  $xhprof_on = true;
3.  ...
4.}
footer.php:
1.if ($xhprof_on) {
2.  $xhprof_data = xhprof_disable();
3.  ...
4.}
Но мы придумали более изящное (а может быть – более костыльное и кривое, кому как покажется) решение.
Для этого на любом сервере (хоть бы и на том же самом) с помощью cron с любой периодичностью запускаем команду:
/usr/bin/wget –no-cookies –header "Cookie: xhprof=1" 'http://mysite/' -o /dev/null -O /mnt/tmpfs/$(/bin/date \+\%Y\%m\%d_\%H\%M\%S)
Тогда на каждый из этих запросов можно будет посмотреть профайл. Ссылку можно либо взять из самой скаченной и сложенной в tmpfs страницы, либо посмотрев файлы с профилями, складывающиеся в xhprof.output_dir. В нашем случае это /tmp. Там при профилировании создаются текстовые файлы вида:
4f9a53e1b44f9.someapp
Хэш из названия файла можно подставить в url вида:
http://mysite:81/callgraph.php?run=4f9a53e1b44f9&source=someapp
XHProf и Drupal
Drupal предоставляет несколько инструментов для взаимодействия с XHProf. Первый – это плагин XHProf (http://drupal.org/project/XHProf), который позволяет отказаться от нативного веб-интерфейса XHProf, от дополнительных виртуальных хостов. И ещё он реализует разные приятные плюшки.
Но мне больше нравится более стандартный плагин Devel, который в своих настройках (admin/config/development/devel) позволяет включить XHProf, если оный модуль для PHP установлен в системе. В настройках также надо указать путь к библиотекам XHProf (/usr/share/php5-xhprof/) и относительный URL, по которому будут доступны результаты профилирования.
Но надо быть готовым к тому, что результат будет слегка зубодробительным.
Ссылки:
PECL:
http://pecl.php.net/package/xhprof
Хорошая статья про XHProf на FreeBSD:
http://adw0rd.ru/2010/freebsd-xhprof-php/
Статья на Хабре:
http://habrahabr.ru/post/78210/

воскресенье, 24 ноября 2013 г.

Запись скринкастов в Ubuntu с помощью ffmpeg




Устанавливаем FFmpeg:
sudo apt-get install ffmpeg

Запускаем запись:
ffmpeg -f x11grab -s 1280×720 -r 25 -i :0.0 -vcodec qtrle screencast.mov

Запускаем запись со звуком:
ffmpeg -f alsa -ac 2 -i hw:0,0 -acodec pcm_s16le -f x11grab -s 1280×720 -r 25 -i :0.0 -vcodec qtrle screencast.mov






Ни одна из программ не отображает клики мыши или нажатия клавиш на клавиатуре, но вы можете воспользоваться программой key-mon.
sudo apt-get install keymon
КлючОписание
-f x11grab источник сигнала
-i :0.0 экран X-сервера / номер монитора
-s 1280×800 захватываемое разрешение экрана
-r 25 количество кадров в секунду
screencast.mov имя выходного файла


Команда для кодирования mov в flv:



ffmpeg -i "имя_файла" -vcodec libx264 -vpre veryfast -crf 25 -ar 22050 -ab 56k -acodec libmp3lame -ac 2 -r 20 -f flv -sameq -s 600x338 "имя_файла.flv"
sudo apt-get install ffmpeg
Запускаем запись:
ffmpeg -f x11grab -s 1280×720 -r 25 -i :0.0 -vcodec qtrle screencast.mov
Запускаем запись со звуком:
ffmpeg -f alsa -ac 2 -i hw:0,0 -acodec pcm_s16le -f x11grab -s 1280×720 -r 25 -i :0.0 -vcodec qtrle screencast.mov

Ни одна из программ не отображает клики мыши или нажатия клавиш на клавиатуре, но вы можете воспользоваться программой key-mon.
sudo apt-get install keymon
КлючОписание
-f x11grabисточник сигнала
-i :0.0экран X-сервера / номер монитора
-s 1280×800захватываемое разрешение экрана
-r 25количество кадров в секунду
screencast.movимя выходного файла


Команда для кодирования mov в flv:



ffmpeg -i "имя_файла" -vcodec libx264 -vpre veryfast -crf 25 -ar 22050 -ab 56k -acodec libmp3lame -ac 2 -r 20 -f flv -sameq -s 600x338 "имя_файла.flv"

Gedit, настройка автоопределения кодировки

gsettings set org.gnome.gedit.preferences.encodings auto-detected "['UTF-8', 'WINDOWS-1251', 'CURRENT', 'ISO-8859-15', 'UTF-16']"

среда, 21 декабря 2011 г.

Создание виртуального хоста

cd /etc/apache2/sites-available/
sudo cp default site.local
sudo gedit site.local

<VirtualHost *:80>
  DocumentRoot "/home/amey/htdocs/
site.local/public"
  ServerName
site.local
  SetEnv APPLICATION_ENV development
  <Directory "/home/amey/htdocs/
site.local/public">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>
</VirtualHost>


добавляем в /etc/hosts:
127.0.0.1 site.local

Включаем хост и рестартим апач:
sudo a2ensite site.local
sudo /etc/init.d/apache2 restart

вторник, 20 декабря 2011 г.

svn merge: приклад використання


Є проект. Назвемо його myproject. В якійсь момент ми форкнули його і створити гілку myproject_unstable. Це нестабільна гілка для усіляких експериментів, хардкорного рефакторинга та іншого.
Після того як дописали багато коду і протестили, нам потрібно всі нові фічі перенести з myproject_unstable в myproject.

Робиться це так:
$ cd workspace/myproject
$ svn merge -r
XXXX:HEAD http://svn.example.com/myproject_unstable --accept theirs-full

XXXX - ревізія, коли була зроблений
гілка
http://svn.example.com/myproject_unstable - гілка, з якої зливаються зміни

Можуть бути конфлікти, svn буде питати, що робити. Можна додати ключ - accept theirs-full, тоді питати не буде, а буде автоматично вирішувати конфлікти на користь входять змін. Тобто конфлікти в даному випадку вирішуватися на
користь гілки myproject_unstable.