Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #68, АВГУСТ 2004 г.

220 на спидометре

Никита Кислицын

Xakep, номер #068, стр. 068-106-1


(nikitoz@real.xakep.ru)

Система для тестирования производительности PHP-программ

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

А оно надо?

Тема действительно интересная, ведь всегда хочется знать, насколько быстро работает та или иная функция, насколько производителен написанный парсер и уступает ли он коммерческому варианту от крутой софтверной фирмы. Подобные тестирования никогда не будут лишними при разработке коммерческих систем или скриптов, рассчитанных на большие нагрузки. Стоит ли говорить, что порой отладка и оптимизация производительности сценариев занимают весьма и весьма значительное время. А обладая вполне конкретными цифрами, можно мысленно выстроить так называемый быстрый синтаксис и использовать только те конструкции, которые работают быстрее всего. Думаю, я тебя убедил, что знать точное время выполнения сценария очень полезно. Но каким же образом можно его измерить?

Как это сделать?

Для этого могут применяться разнообразные внешние по отношению к скрипту программы, работающие на уровне межпроцессовых взаимодействий. Однако на практике куда проще и функциональнее использовать для этих нужд собственные возможности языка программирования. Если рассматривать PHP, тут есть две базовые функции, которые помогут нам решить эту проблему. Первая из них хорошо тебе знакома - это time(). Как ты знаешь, она возвращает количество секунд, прошедших с начала Эпохи. Соответственно, если мы запомним значение этой функции в начале работы сценария и вычтем его из значения в конце работы, получится время выполнения в секундах. Однако подумай сам - обычно процесс выполняется доли секунды, во всяком случае, разница во времени работы базовых функций будет меньше на несколько порядков такой точности измерения. Что же делать? Тут на помощь приходит другая, более полезная функция microtime(), которая возвращает значение timestamp, не округляя его. Нам становится доступно сравнительно точное значение текущего времени, и мы можем нормально посчитать время выполнения даже самого маленького кусочка кода. Следует заметить, что обе функции - и time() и microtime() являются в известном смысле дискретными, поэтому точность такого измерения заведомо ограничена, однако и ее нам хватит с головой. В принципе, тут все ясно. Берется кусок кода, в его начале вычисляется функция microtime и ее значение запоминается в переменной $start. Затем в конце блока кода заново вычисляется значение этой функции, и если теперь вычесть из этой цифры запомненное значение $start, мы получим время работы этого кода с точностью до зверских долей секунды. Думаю, тут все понятно - во, даже Бублик кивает, что понятно. Ну раз так, отлично. А что если ты тестируешь систему, состоящую из нескольких десятков различных файлов, общим объемом в несколько десятков тысяч строк? Представляешь, какой это геморрой - вставлять однотипные куски кода, создавать кучу новых переменных, выводить результаты и т.д. Это оказывается очень неудобным. По этой причине я решил написать систему, измеряющую производительность в пространстве нескольких "процессов", вернее, блоков кода. Ясно, что здесь этот термин не совсем подходит, но для краткости ниже я буду использовать именно его.

Содержание  Вперед на стр. 068-106-2