Поэтому возникла идея написать собственный механизм простого тестирования скорости различных операций. Задумка показалась интересной, поэтому начало было положено!
Цели
Начать следовало с постановки целей будущего инструмента. Проект хотелось видеть как универсальный инструмент для тестирования скорости чего угодно. Но поразмыслив над деталями
Итак, требовалось получить инструмент, который:
- сравнивает скорость выполнения различных функций
- имеет возможность использования заранее подготовленных тестов
- выводит в читаемом виде результат
- имеет возможность создания собственных тестов и вариантов представления результатов
- может быть легко использован на других платформах
Механизм замеров
Для замера времени выполнения функции было решено воспользоваться подобным, методом
protected function getTime($time = false)
{
return $time === false? microtime(true) : microtime(true) - $time;
}
Принцип действия прост, если происходит вызов без параметров, то возвращаем текущее состоянии времени, если же вызов происходит с параметром времени, тогда возвращается разница между текущим и переданным временем.
Но там где расчет времени, там же и потребляемый объем памяти, поэтому в последствии был добавлен аналогичный метод измерения потребляемой памяти.
protected function getMemory($memory = false)
{
return $memory === false? memory_get_usage() : memory_get_usage() - $memory;
}
Механизм аналогичен механике замера времени, только в данном случае происходит передача значения выделенной памяти скрипту.
Как известно, некоторые функции ведут себя по разному в зависимости от входного набора данных, поэтому в каждом тесте определен массив входных данных для функций тестирования. Для получения наиболее точных результатов, тестирование функций проводится на каждом наборе несколько раз. Помимо прочего, тестирование проводится в разной последовательности.
В ходе экспериментов, было замечено, что объем свободной памяти перед началом каждого теста разный, хоть для большинства проводимый испытаний это было незначительным, но для порядка хотелось бы иметь условия одинаковые для всех испытаний либо близкие к таковым. Поэтому хранение результатов было решено реализовать в локальном хранилище SQLite, а перед началом испытаний делать один проверочный тест для заполнения переменных данными.
Для того, чтобы иметь возможность создания собственных вариантов представления результатов и собственных вариантов теста, создано 2 модели абстракции. Модель тестов (Test), содержит всю информацию о тесте, включая функции тестирования. Модель представления данных (DataViwer) содержит методы преобразования результатов тестирования в читаемый вид. Для удобного вывода представлений был задействован шаблонизатор Twig и подключена библиотека стилей bootstrap, также создан вьювер с графиком HighCharts.
В итоге общий механизм работы такой. Берутся необходимые для сравнения функции и запускаются на выполнение с разными наборами данных и в разной последовательности. При этом происходит замер времени каждого выполнения и запись результата в хранилище. За данный этап отвечает модель теста (Test). После всех замеров происходит передача результатов в представление данных (DataViwer), где происходит обработка и вывод информации.
Реализация тестирования
Класс теста
Простой пример реализации класса теста, на примере тестирования скорости выполнения операции пред инкрементирования и пост инкрементирования.
class IncPrefVsPos extends TestAbstract
{
public $name = 'Speedy ++i vs i++';
public $valueTest = [100, 1000, 2000, 3000];
public $qntTest = 5;
public $viewers = [TestCore::VIEWER_TLIST, TestCore::VIEWER_TGROUP, TestCore::VIEWER_TAVG, TestCore::VIEWER_GBUBLE];
public $functions = ['postIncrement' => 'testPost', 'prefIncrement' => 'testPref'];
protected $strategy = [['testPost', 'testPref'], ['testPref', 'testPost']];
public function testPref($size)
{
$testCounter = 0;
for($i=0;$i<$size;$i++) {
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
}
}
public function testPost($size)
{
$testCounter = 0;
for($i=0;$i<$size;$i++) {
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
}
}
}
Класс должен наследовать абстрактный класс TestAbstract, в котором заложена основная механика работы с потоками данных.
$name — задает название теста, которое может быть использовано при выводе в DataViewer.
$valueTest — объем выборки тестирования, массив значений, с каждым из которых будет выполнена функция для тестирования. Таким образом каждая тестируемая функция должна обязательно принимать один параметр. Будет он являться числом, строкой или массивом не важно, все зависит от конкретного случая. В нашем примере, достаточно чисел, которые будут обозначать объем проводимых операций с инкрементом.
$qntTest — говорит о том, какое количество раз будет протестирован каждый объем выборки.
$viewers — массив представлений данных, который будет сформирован при рендере отчета. На самом деле это набор полных имен классов наследующих абстрактный класс ViewrAbstract. Заранее подготовленные вьюверы вынесены в константы класса TestCore.
$functions — массив названий функций которые будут использоваться в тестировании. Ключами массива являются названия, которые будут отображены в результатах.
$strategy — массив стратегий тестирования, каждая стратегия должна быть представлена массивом с последовательностью имен функций. В примере указано 2 стратегии — прямой последовательности и в обратной.
Непосредственно сами функции, которые как говорилось выше, должны принимать одно значение. В нашем примере, мы считаем это за количество выполняемых операций серии инкрементирования.
В итоге получим, серию тестов где каждая стратегия тестирования будет протестирована по 5 раз с каждым объемом выборки ([100, 1000, 2000, 3000]).
Класс представления данных
Сейчас давайте подробнее рассмотрим простой класс представления данных.
class TableList extends ViewerAbstract
{
public $view = 'tableList.php';
public function generateData($data){
return $data;
}
public function run($data)
{
$data = $this->generateData($data);
return App::render('/viewer/'.$this->view, compact('data'));
}
public static function model($class = __CLASS__) {
return parent::model($class);
}
}
Класс реализует абстрактный класс ViewerAbstract.
$view — содержит имя представления, которое поумолчанию должно лежать в папке /views/viewers
function generateData($data) — метод обработки массива результатов тестирования. Результат будет передан поумолчанию в параметр data в указанное представление.
function run($data) — необязательный для реализации метод, но если необходимо изменить путь к представлению данных, то именно он должен быть переопределен.
public static function model($class = __CLASS__) — метод поддержки статического обращения к методам
Варианты использования
Чтобы воспользоваться функционалом тестирования, создано 2 основных метода.
Метод запуска теста
function test($test, $params = [], $onlyData = false)
$test — полное имя запускаемого теста. Могут быть задействованы как свои варианты тестов либо заранее подготовленные.
$params — массив параметров для запуска теста. Данным параметром можно точечно изменить параметры тестирования.
$onlyData — параметр отвечающий за вывод набора результатов либо отрендеренное представление.
Метод сравнения функций
Метод сравнения пользовательских функций без создания дополнительных классов
function compare($func = [], $params = [], $onlyData = false)
$func — массив анонимных функций, где ключи массива являются названиями функций в результатах тестирования.
$params — массив параметров тестирования, аналогичен параметрам метода test.
$onlyData — также аналогичен параметру метода test, и отвечает за вариант вывода результатов.
Примеры работы
Самый простой и быстрый вариант использования — это воспользоваться заранее подготовленным тестом. Все подготовленные тесты вынесены в константы класса Speedy.
print Speedy::test(Speedy::PHP_SOF_VS_COUNT);
Для сравнения пользовательских функций, необходимо создать анонимные функции и вызвать метод Speedy::compare
$pref = function($size)
{
$testCounter = 0;
for($i=0;$i<$size;$i++) {
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter; ++$testCounter;
}
};
$post = function($size)
{
$testCounter = 0;
for($i=0;$i<$size;$i++) {
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
$testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++; $testCounter++;
}
};
print \speedy\Speedy::compare(['pref' => $pref, 'post' => $post]);
Результаты тестирования
Результаты тестирования на данный момент могут быть выведены 4мя представлениями.
VIEWER_TLIST
Представление в табличной форме списка всех произведенных замеров времени. По сути это вывод всех записей из хранилища, без каких-либо преобразований. В наборе данных содержится информация о имени тестируемой функции, затраченном времени, объему выборки, используемому объему памяти, номер партии в которой выполнялся тест и комментарий. В комментарии указывается в рамках какой стратегии был выполнен тест данной функции.
name | time | size | memory | part | comment |
postInc | 0.000650882720947 | 100 | 48 | 2 | postInc-prefInc |
prefInc | 0.000411987304688 | 100 | 48 | 2 | postInc-prefInc |
prefInc | 0.000406980514526 | 100 | 48 | 3 | prefInc-postInc |
postInc | 0.000549077987671 | 100 | 48 | 3 | prefInc-postInc |
postInc | 0.000330924987793 | 100 | 48 | 5 | postInc-prefInc |
prefInc | 0.000287055969238 | 100 | 48 | 5 | postInc-prefInc |
prefInc | 0.00043797492981 | 100 | 48 | 6 | prefInc-postInc |
postInc | 0.000365018844604 | 100 | 48 | 6 | prefInc-postInc |
postInc | 0.000295162200928 | 100 | 48 | 8 | postInc-prefInc |
prefInc | 0.000373125076294 | 100 | 48 | 8 | postInc-prefInc |
prefInc | 0.000263929367065 | 100 | 48 | 9 | prefInc-postInc |
postInc | 0.000449895858765 | 100 | 48 | 9 | prefInc-postInc |
postInc | 0.00030517578125 | 100 | 48 | 11 | postInc-prefInc |
prefInc | 0.000247955322266 | 100 | 48 | 11 | postInc-prefInc |
prefInc | 0.000244140625 | 100 | 48 | 12 | prefInc-postInc |
postInc | 0.000265121459961 | 100 | 48 | 12 | prefInc-postInc |
postInc | 0.000267028808594 | 100 | 48 | 14 | postInc-prefInc |
prefInc | 0.000245094299316 | 100 | 48 | 14 | postInc-prefInc |
prefInc | 0.000285148620605 | 100 | 48 | 15 | prefInc-postInc |
postInc | 0.000273942947388 | 100 | 48 | 15 | prefInc-postInc |
postInc | 0.00273203849792 | 1000 | 48 | 17 | postInc-prefInc |
prefInc | 0.00240206718445 | 1000 | 48 | 17 | postInc-prefInc |
prefInc | 0.00274896621704 | 1000 | 48 | 18 | prefInc-postInc |
postInc | 0.00259804725647 | 1000 | 48 | 18 | prefInc-postInc |
postInc | 0.00391817092896 | 1000 | 48 | 20 | postInc-prefInc |
prefInc | 0.00303602218628 | 1000 | 48 | 20 | postInc-prefInc |
prefInc | 0.00229096412659 | 1000 | 48 | 21 | prefInc-postInc |
postInc | 0.00281691551208 | 1000 | 48 | 21 | prefInc-postInc |
postInc | 0.00273108482361 | 1000 | 48 | 23 | postInc-prefInc |
prefInc | 0.00221014022827 | 1000 | 48 | 23 | postInc-prefInc |
prefInc | 0.00266814231873 | 1000 | 48 | 24 | prefInc-postInc |
postInc | 0.00307106971741 | 1000 | 48 | 24 | prefInc-postInc |
postInc | 0.00283098220825 | 1000 | 48 | 26 | postInc-prefInc |
prefInc | 0.00239992141724 | 1000 | 48 | 26 | postInc-prefInc |
prefInc | 0.00246214866638 | 1000 | 48 | 27 | prefInc-postInc |
postInc | 0.00273704528809 | 1000 | 48 | 27 | prefInc-postInc |
postInc | 0.00283288955688 | 1000 | 48 | 29 | postInc-prefInc |
prefInc | 0.00229215621948 | 1000 | 48 | 29 | postInc-prefInc |
prefInc | 0.00220608711243 | 1000 | 48 | 30 | prefInc-postInc |
postInc | 0.0028657913208 | 1000 | 48 | 30 | prefInc-postInc |
postInc | 0.00557017326355 | 2000 | 48 | 32 | postInc-prefInc |
prefInc | 0.0048840045929 | 2000 | 48 | 32 | postInc-prefInc |
prefInc | 0.00449013710022 | 2000 | 48 | 33 | prefInc-postInc |
postInc | 0.0064799785614 | 2000 | 48 | 33 | prefInc-postInc |
postInc | 0.00543594360352 | 2000 | 48 | 35 | postInc-prefInc |
prefInc | 0.00509881973267 | 2000 | 48 | 35 | postInc-prefInc |
prefInc | 0.00483298301697 | 2000 | 48 | 36 | prefInc-postInc |
postInc | 0.00555992126465 | 2000 | 48 | 36 | prefInc-postInc |
postInc | 0.00516104698181 | 2000 | 48 | 38 | postInc-prefInc |
prefInc | 0.00512599945068 | 2000 | 48 | 38 | postInc-prefInc |
prefInc | 0.00484395027161 | 2000 | 48 | 39 | prefInc-postInc |
postInc | 0.00530505180359 | 2000 | 48 | 39 | prefInc-postInc |
postInc | 0.00509691238403 | 2000 | 48 | 41 | postInc-prefInc |
prefInc | 0.00525093078613 | 2000 | 48 | 41 | postInc-prefInc |
prefInc | 0.00447416305542 | 2000 | 48 | 42 | prefInc-postInc |
postInc | 0.00536584854126 | 2000 | 48 | 42 | prefInc-postInc |
postInc | 0.0054669380188 | 2000 | 48 | 44 | postInc-prefInc |
prefInc | 0.00468182563782 | 2000 | 48 | 44 | postInc-prefInc |
prefInc | 0.00512504577637 | 2000 | 48 | 45 | prefInc-postInc |
postInc | 0.00545692443848 | 2000 | 48 | 45 | prefInc-postInc |
postInc | 0.00782418251038 | 3000 | 48 | 47 | postInc-prefInc |
prefInc | 0.00726389884949 | 3000 | 48 | 47 | postInc-prefInc |
prefInc | 0.00674796104431 | 3000 | 48 | 48 | prefInc-postInc |
postInc | 0.007483959198 | 3000 | 48 | 48 | prefInc-postInc |
postInc | 0.00781297683716 | 3000 | 48 | 50 | postInc-prefInc |
prefInc | 0.0069580078125 | 3000 | 48 | 50 | postInc-prefInc |
prefInc | 0.00711393356323 | 3000 | 48 | 51 | prefInc-postInc |
postInc | 0.0072808265686 | 3000 | 48 | 51 | prefInc-postInc |
postInc | 0.00790119171143 | 3000 | 48 | 53 | postInc-prefInc |
prefInc | 0.00662994384766 | 3000 | 48 | 53 | postInc-prefInc |
prefInc | 0.00825595855713 | 3000 | 48 | 54 | prefInc-postInc |
postInc | 0.00739097595215 | 3000 | 48 | 54 | prefInc-postInc |
postInc | 0.00811100006104 | 3000 | 48 | 56 | postInc-prefInc |
prefInc | 0.00712990760803 | 3000 | 48 | 56 | postInc-prefInc |
prefInc | 0.00698399543762 | 3000 | 48 | 57 | prefInc-postInc |
postInc | 0.00758218765259 | 3000 | 48 | 57 | prefInc-postInc |
postInc | 0.00795316696167 | 3000 | 48 | 59 | postInc-prefInc |
prefInc | 0.00725698471069 | 3000 | 48 | 59 | postInc-prefInc |
prefInc | 0.00684094429016 | 3000 | 48 | 60 | prefInc-postInc |
postInc | 0.00778198242188 | 3000 | 48 | 60 | prefInc-postInc |
VIEWER_TGROUP
Представление в табличной форме в виде сгруппированных данных по партии тестирования (по номеру прохода по стратегии), т.е. в одной строке окажутся результаты тестирования функций которые проводились в рамках одной стратегии и в рамках одного прохода теста.
В столбцах таблицы будут отображены данные о размере выборки, времени выполнения, проценту скорости от худшего результата, затраченной памяти, комментария и названия функции, которая стала победителем по времени среди текущего прохода. Отдельно хотелось бы пояснить столбец процента. Данное значение высчитывается как процент, на сколько по времени функция опередила выполнение самой медленной функции. Если значение не установлено, значит эта функция по времени выполнения является аутсайдером в проходе.
size | postInc | prefInc | comment | time win | ||||
time | % | memory | time | % | memory | |||
100 | 0.000650882720947 | 48 | 0.000411987304688 | 36.7 | 48 | postInc-prefInc | prefInc | |
100 | 0.000549077987671 | 48 | 0.000406980514526 | 25.88 | 48 | prefInc-postInc | prefInc | |
100 | 0.000330924987793 | 48 | 0.000287055969238 | 13.26 | 48 | postInc-prefInc | prefInc | |
100 | 0.000365018844604 | 16.66 | 48 | 0.00043797492981 | 48 | prefInc-postInc | postInc | |
100 | 0.000295162200928 | 20.89 | 48 | 0.000373125076294 | 48 | postInc-prefInc | postInc | |
100 | 0.000449895858765 | 48 | 0.000263929367065 | 41.34 | 48 | prefInc-postInc | prefInc | |
100 | 0.00030517578125 | 48 | 0.000247955322266 | 18.75 | 48 | postInc-prefInc | prefInc | |
100 | 0.000265121459961 | 48 | 0.000244140625 | 7.91 | 48 | prefInc-postInc | prefInc | |
100 | 0.000267028808594 | 48 | 0.000245094299316 | 8.21 | 48 | postInc-prefInc | prefInc | |
100 | 0.000273942947388 | 3.93 | 48 | 0.000285148620605 | 48 | prefInc-postInc | postInc | |
1000 | 0.00273203849792 | 48 | 0.00240206718445 | 12.08 | 48 | postInc-prefInc | prefInc | |
1000 | 0.00259804725647 | 5.49 | 48 | 0.00274896621704 | 48 | prefInc-postInc | postInc | |
1000 | 0.00391817092896 | 48 | 0.00303602218628 | 22.51 | 48 | postInc-prefInc | prefInc | |
1000 | 0.00281691551208 | 48 | 0.00229096412659 | 18.67 | 48 | prefInc-postInc | prefInc | |
1000 | 0.00273108482361 | 48 | 0.00221014022827 | 19.07 | 48 | postInc-prefInc | prefInc | |
1000 | 0.00307106971741 | 48 | 0.00266814231873 | 13.12 | 48 | prefInc-postInc | prefInc | |
1000 | 0.00283098220825 | 48 | 0.00239992141724 | 15.23 | 48 | postInc-prefInc | prefInc | |
1000 | 0.00273704528809 | 48 | 0.00246214866638 | 10.04 | 48 | prefInc-postInc | prefInc | |
1000 | 0.00283288955688 | 48 | 0.00229215621948 | 19.09 | 48 | postInc-prefInc | prefInc | |
1000 | 0.0028657913208 | 48 | 0.00220608711243 | 23.02 | 48 | prefInc-postInc | prefInc | |
2000 | 0.00557017326355 | 48 | 0.0048840045929 | 12.32 | 48 | postInc-prefInc | prefInc | |
2000 | 0.0064799785614 | 48 | 0.00449013710022 | 30.71 | 48 | prefInc-postInc | prefInc | |
2000 | 0.00543594360352 | 48 | 0.00509881973267 | 6.2 | 48 | postInc-prefInc | prefInc | |
2000 | 0.00555992126465 | 48 | 0.00483298301697 | 13.07 | 48 | prefInc-postInc | prefInc | |
2000 | 0.00516104698181 | 48 | 0.00512599945068 | 0.68 | 48 | postInc-prefInc | prefInc | |
2000 | 0.00530505180359 | 48 | 0.00484395027161 | 8.69 | 48 | prefInc-postInc | prefInc | |
2000 | 0.00509691238403 | 2.93 | 48 | 0.00525093078613 | 48 | postInc-prefInc | postInc | |
2000 | 0.00536584854126 | 48 | 0.00447416305542 | 16.62 | 48 | prefInc-postInc | prefInc | |
2000 | 0.0054669380188 | 48 | 0.00468182563782 | 14.36 | 48 | postInc-prefInc | prefInc | |
2000 | 0.00545692443848 | 48 | 0.00512504577637 | 6.08 | 48 | prefInc-postInc | prefInc | |
3000 | 0.00782418251038 | 48 | 0.00726389884949 | 7.16 | 48 | postInc-prefInc | prefInc | |
3000 | 0.007483959198 | 48 | 0.00674796104431 | 9.83 | 48 | prefInc-postInc | prefInc | |
3000 | 0.00781297683716 | 48 | 0.0069580078125 | 10.94 | 48 | postInc-prefInc | prefInc | |
3000 | 0.0072808265686 | 48 | 0.00711393356323 | 2.29 | 48 | prefInc-postInc | prefInc | |
3000 | 0.00790119171143 | 48 | 0.00662994384766 | 16.09 | 48 | postInc-prefInc | prefInc | |
3000 | 0.00739097595215 | 10.48 | 48 | 0.00825595855713 | 48 | prefInc-postInc | postInc | |
3000 | 0.00811100006104 | 48 | 0.00712990760803 | 12.1 | 48 | postInc-prefInc | prefInc | |
3000 | 0.00758218765259 | 48 | 0.00698399543762 | 7.89 | 48 | prefInc-postInc | prefInc | |
3000 | 0.00795316696167 | 48 | 0.00725698471069 | 8.75 | 48 | postInc-prefInc | prefInc | |
3000 | 0.00778198242188 | 48 | 0.00684094429016 | 12.09 | 48 | prefInc-postInc | prefInc |
VIEWER_TAVG
Представление в табличной форме в виде усредненных показателей по размеру выборки, т.е. в одной строке окажутся средние показатели тестирования функций по одной выборке.
В столбцах представлена информация по количеству побед функции в выборке, средний процент времени побед, имя функции-победителя. Функции-победитель — определяется количеством побед в выборке.
size | postInc | prefInc | winner | ||
winns | % | winns | % | ||
100 | 3 | 13.83 | 7 | 21.72 | prefInc |
1000 | 1 | 5.49 | 9 | 16.98 | prefInc |
2000 | 1 | 2.93 | 9 | 12.08 | prefInc |
3000 | 1 | 10.48 | 9 | 9.68 | prefInc |
VIEWER_GBUBLE
Представление в графической форме в виде набора точек, каждая из которых соответствует значению времени и объему выборки. Данное представление реализовано при помощи графиков HighCharts.
![image](https://habrastorage.org/getpro/habr/post_images/56c/3e6/d74/56c3e6d74542071b5d1e789c65477dab.png)
Итоги
Подытожить хотелось бы тем, что поставленные цели были достигнуты. Но конечно же еще есть над чем поработать. В планах работа над обработкой исключений, добавление возможности смены в настройках набора столбцов а также возможность задавать собственные имена столбцам, увеличение количества тестов. Также хотелось бы добавить возможность удобного тестирования скорости работы с базами данных.
Исходный код проекта можно смотреть здесь
P.S.: Данный проект разрабатывается в рамках личного интереса к данной теме и не претендует на место лучшего в своем роде. Буду рад, если кому-то понравится и будет полезен данный труд. Конструктивная критика и советы приветствуются.
Комментарии (44)
Diaskhan
27.08.2016 20:53-48Php программерам вообще слабо знакомо такое понятие как отладчик, отладчик в их понимании это Chrome )) уж простите за сарказм.
Месяца четыре мусолил одному программеру на Php перейтй c notepad++ на phpstorm, Второму мусолил пол года, второй тока через два года перешел на phpstorm, видимо компетентность и пхп понятия не совместимые… надо бы статью написать что пользоваться plain text редакторами это зло.SerafimArts
27.08.2016 22:04+12А как ваш опыт общения с кодерами относится к "php программерам"? Просто потому что языки совпали и вы сразу за всех решили?
Delphinum
27.08.2016 22:08+6В субботу хабра-выпилы не такие эпичные ((
Diaskhan
27.08.2016 22:26-28Вы уж извините меня php программеры, просто не часто в топиках встретишь java C# и питон програмеров. Хватит меня провацировать еще на минусы ))
тут вопрос в другом, Многие программеры которые считают себя гуру программерами редко пользуются форматированием кода. Редко считают что стандарты к ним относится. а использование IDE, подразумевает использование стандартных фишек IDE, и в следствие использование gofmt по умолчанию…
Вообще если быть серьезным то множество компаний которые использует ПХП, делают по больше части сайты для пиара (landing pages), а не какие то серьезные веб приложения со сложной бизнес логикой.
но Php способен не только на Wordpress! А вообще php слишком молод для того чтобы по умолчанию принимали профилирование как по умолчанию. Любой платформе-технологии нужно какое то время чтобы понять что есть проблемы утечек, синхронизации потоков, утиной типизации и то что в принципе php придумывалось как Personal Home Page Tools. Этим и обусловлено недальновидность таких парадигм как потоки, утечки памяти и вещей которые не созданы чтобы умирать https://habrahabr.ru/post/179399/TODOOM
28.08.2016 01:16+11Вы уж извините меня php программеры, просто не часто в топиках встретишь java C# и питон програмеров. Хватит меня провацировать еще на минусы ))
Подписывайтесь на соответствующие «хабы».
тут вопрос в другом, Многие программеры которые считают себя гуру программерами редко пользуются форматированием кода. Редко считают что стандарты к ним относится. а использование IDE, подразумевает использование стандартных фишек IDE, и в следствие использование gofmt по умолчанию…
Многие? У Вас есть соответствующая статистика?
И да, считать себя «гуру» ничего не значит. Все решает: 1) знания; 2) опыт применения; 3) практика использования собственного опыта.\
И IDE — это всего лишь инструмент, и он способствует появлению джуниоров с замашками сеньора.
При чем тут форматирование кода и IDE? Во 1) форматирование кода определяется проектом/командой/требованиями: во 2) IDE (в качестве примера указанный PhpStorm || IntelliJ IDEA (что более верно)) как инструмент представляет функции автоформатирования (до сих пор кривого) с параметрами «по умолчанию» которые не являются стандартом (вопрос еще каким).
Вообще если быть серьезным то множество компаний которые использует ПХП, делают по больше части сайты для пиара (landing pages), а не какие то серьезные веб приложения со сложной бизнес логикой.
Множество? Откуда инфа?..
Предположим какой-то % использует. И что? Где логика? Лендинги — это в первую очередь «красота» (не случайно в кавычках, т.к. все мы знаем к чему приводят попытки искусственно повысить конверсию). Но, что за этим скрывается?
Давайте подумаем. Наверное бэкэнд, который должен вычислять конверсию для (???)… Точно! Чего угодно. Добро пожаловать за кулисы мат. фака.
но Php способен не только на Wordpress! А вообще php слишком молод для того чтобы по умолчанию принимали профилирование как по умолчанию. Любой платформе-технологии нужно какое то время чтобы понять что есть проблемы утечек, синхронизации потоков, утиной типизации и то что в принципе php придумывалось как Personal Home Page Tools. Этим и обусловлено недальновидность таких парадигм как потоки, утечки памяти и вещей которые не созданы чтобы умирать https://habrahabr.ru/post/179399/
Хватит читать всякий бред.Нет-нет, конечно, читайте! Это полезно. Но включайте мозг.
Мог бы вам поставить диагноз — хабродроб, но я не доктор.
Если вы разработчик, то примите факт — вы разработчик. Язык — это всего лишь инструмент.
Умейте пользоваться Вашим инструментом, в жизни пригодится.
К слову, не фанат wordpress, но это не означает, что он является чем-то «юродивым». Это всего-лишь CMS. Как бы сказал: «не умеешь использовать — иди дальше».Delphinum
28.08.2016 10:48-11Если вы разработчик, то примите факт — вы разработчик. Язык — это всего лишь инструмент
Разработчик разрабатывает, языками (программирования) пользуются программисты.
HeadOnFire
28.08.2016 16:41+3Ыы. А куда идти тем, кто пишет на PHP, использует и WordPress тоже (в том числе для весьма больших и сложных проектов с непростой бизнес логикой и интеграцией с другими платформами), использует PHPStorm (о боги, даже лицензионный!), пишет тесты, юзает CodeSniffer, задрачивает всю команду требованием придерживаться Coding Standards, профилирует и дебажит код так, что при передаче проекта клиенту тестирование не выявляет проблем и со временем работы проекта проблем не возникает (даже на крупных и сильно посещаемых проектах, даже если они запилены на WordPress) и так далее и тому подобное. При этом гуру себя никто не считает и не гуглит в гугле. Куда пройти, не подскажете?
cry_san
29.08.2016 04:09Я не понимаю, чем не устроил notepad++?
SerafimArts
29.08.2016 05:27Ну для быстрого редактирования файлика-двух он вполне подходит, никто не спорит.
aleks_raiden
29.08.2016 17:03откройте еще мир плагинов к нему и будет все ок )))
SerafimArts
29.08.2016 21:58+1Если бы всё было так просто, то не было бы таких инструментов как шторм ;)
AmdY
29.08.2016 20:27Когда человек путает отладку и профилирование, это говорит больше о его квалификации, нежели php-шников.
К сожалению, в учебных заведениях курсы в основном рассчитаны на .net-java разработчиков и они преподаются на порядок лучше, а среди php-шников в основном самоучки, потому на входе знания поменьше. Но если не подаваться в «диджитал» и «молодые амбициозные» компании, то за первых же пару месяцев всё осваивается, и ide, и отладка, и профилирование, и тестирование, и ещё 100500 вещей, которые не особо привязаны к языку.
VitaZheltyakov
27.08.2016 21:40+4xDebug, трассировка… достаточно лишь научится использовать и в ваших руках будет полная информация о производительности скриптов
SerafimArts
27.08.2016 22:05+6xhprof, кстати, в данном случае на порядок удобнее.
Punk_UnDeaD
28.08.2016 20:58Удобнее, чем добавить по вызову с замерами времени до и после нужной функции? На порядок?
SerafimArts
29.08.2016 05:29
IIISpikerIII
28.08.2016 01:33Возможно я не знаю всех тонкостей xDebug, но помоему он не предоставляет возможности проведения множества испытаний с разным набором данных и формирования результирующего сравнительного представления. Тоесть если такое и возможно, то необходимо создание обработчика для xDebug. Всех ближе к тому, что хотелось бы получить Xhprof, но опять же требуются доработки. Я считаю, что реализация на PHP имеет место на существование, поскольку обладает такими плюсами как возможность расширения и легкость установки.
AterCattus
27.08.2016 21:45+1Вы бы хоть какое-то достаточное число итераций делали, чтобы не получались эти замеры 0.0028, сопоставимые с погрешностями.
В go, к примеру, встроенный бенчмарк подбирает число итераций у разных тестов, чтобы они все поработали достаточно и сопоставимое время.IIISpikerIII
28.08.2016 01:47Про идею подбора количества итераций понял.
Про замеры, в данном случае машинные погрешности исключаются не за счет объема выборки (вы скорее всего имели это ввиду) а какраз за счет количества итераций. На графике можно проследить, что даже с таким объемом выборки время выполнения одной функции превышает, а с увеличением объема разница становится существеннее. Но соглашусь, что при бОльшем объеме это было бы еще заметнее.
edogs
27.08.2016 23:24+5memory_get_usage() — не найс, ибо показывает количество памяти после вызова функции, а не сколько функция потребляет при работе. А поскольку после окончания вызова функции память которую она занимала освобождается — не удивительно, что потребляемая память у Вас всегда одна и та же — 48.
Если уж хотите колхозить, то для памяти колхозьте через http://php.net/memory_get_peak_usage, но правда придется следовать идее «один запуск пхп — один тест», т.к. иначе не всегда будет понятно чей именно пик зафиксирован.
alexsocute
29.08.2016 09:47Остается понять, что проще и выгоднее на момент времени: сидение с дебагом и оптимизация существующих скриптов, или расширение технической платформы на которой выполняется скрипт. Как показывает моя практика, второе всегда выгоднее.
Да и вообще, если говорить в общем о большинстве проектов (и большинство — WEB приложения, оптимизация будет двигаться по этому списку:
1. SQL-оптимизация
2. Оптимизация софта отдачи (NGINX, Apache и прочее. Намеренно использовать -end'ы, чтоб не запутаться)
3. Оптимизация дисковой системы
...100. Оптимизация скриптов PHP.
Я думаю многие согласятся, что сейчас скрипты делают максимально разделенными и простыми. Там нет супер вычислений. В основном — взять из базы, отформатировать и вывести. Или проверить входные данные и записать в базу.
Zebratuk
29.08.2016 09:48Ожидалось нечто «внутреннее» по заголовку. А по факту — есть же отличные профайлеры. Тот-же blackfire поможет «в один клик» собрать статистику, при том несколько (что-то изменили после очередной итерации «улучшения») слепков и между собой эти слепки сравнить.
А тест посредством замера скорости и получения данных по памяти (не забываем, что «даже» php умеет мусор убирать за собой не будучи убитым) — скорее что-то на коленке и очень прямо сейчас, или совсем нет возможности добавить расширение любимого профайлера.
p.s. Для профилировки памяти можно http://php.net/manual/ru/function.register-tick-function.php прикрутить. Но это на скорость исполнения даст прирост.
smple
29.08.2016 14:02к сожалению использование такого анализа скорости я бы не рекомендовал
посмотрите в сторону профилировщиков, например xdebug https://xdebug.org/docs/profilerIIISpikerIII
29.08.2016 14:10Согласен, что любым профилировщиком можно получить много информации и он очень удобен для отладки. Даже для получения усредненных данных в текущем проекте можно добавить замеры с помощью профилировщика, но на сколько здесь будет это обоснованно? Ведь для замеров времени и памяти достаточно одного PHP а для голой установки не будет требования в наличии профилировщика.
Delphinum
29.08.2016 14:25Для запуска Web-сервера тоже достаточно одного PHP, давайте отказываться от Apache с Nginx?
smple
29.08.2016 14:31ваш сарказм я конечно понял.
но уже довольно давно есть движения в этом направление https://daemon.io/ и http://reactphp.org/
причем у последнего при запуске различных бенчмарков для framework получили преимущества.
Тут не совсем отказ от nginx там скорее отказ от php fpm, но никто не мешает использовать reactphp и nginx вместо php-fpm и nginx.
Да я понимаю что серьезный проект на такое переводить не стоит, но поиграться, вполне можно.IIISpikerIII
29.08.2016 14:53Возможно не так понят посыл проекта, это не замена и не альтернатива профилировщику. В дальнейшем хотелось бы создать набор классов-тестов где будет происходить сравнение аналогичных по конечному результату функций/алгоритмов, как они себя ведут при разных значениях параметров, с возможностью легко развернуть и проверить на своей стороне результат.
smple
29.08.2016 14:26погрешность при измерение данным способом может быть значительной, по сравнению с profiler.
если устраивает погрешность то хорошо, но я бы выбрал xdebug profiler более точен, существуют готовые инструменты визуализации, субъективно более привычный.
Попробуйте взять одну и туже функцию и замерить ее (несколько раз) с помощью вашего класса и с помощью xdebug и посмотрите на сколько различаются данные между собой и на сколько они отличаются их средние и каков разброс величин.IIISpikerIII
29.08.2016 14:37Да, если будем сравнивать профайлер с данным способом различия могут быть, но ведь в нашем случае производим замеры 2х функций при одинаковых условиях, тоесть время выполнения функций может иметь какую-то погрешность, но относительно друг друга они должны иметь сопоставимые результаты.
maxru
29.08.2016 15:20Так что быстрее — echo или print?
Хотелось бы всё-таки через 15 лет раз и навсегда уяснить.
oxidmod
чего не придумают, лишь бы нормальный профилировщик не использовать