fenom-template / fenom

Template Engine for PHP. Maintainers wanted!
Other
446 stars 108 forks source link

Скорость штатного запуска. #126

Closed f0mich closed 9 years ago

f0mich commented 9 years ago

Наткнулся на хабре в коментариях про феном на кусок холивара "шаблонизатор vs голый пхп", где коментатор привел небольшую статистику что у него голый пхп в 2 раза быстрее чем феном. На что Иван ответил "хотя странно что феном почти в 2 раза сдает нативному PHP ведь он конвертит в нативный PHP " решил проверить - взял из документации шаблон greetings убрал от туда инклуды (для простоты теста), скопировал в 10 файлов (у меня чаще всего шаблоны это много мальених малозависящих друг от друга файлов) и запустил - 0.01ххх секунды. Потом взял один из скомпилированных файлов, заменил там "new Fenom\Render" на array, сделал небольшую функицию заменяющую собой рендер (тоесть поидее рендер должен проверить не изменился ли файл, и если не изменился то запустить его) function loadtemplate($tmp, $var) { global $fenom; if (filemtime(DIR."/compiled/$tmp")); $a = include("./compiled/$tmp"); $a [ 1 ] ( $var, '' ); } так же запустил эту функцию 10 раз. результат 0.004-0.005 Чем же таким занимается ренден фенома что скомпиленные феномом шаблоны без феномского рендера работают в 2 раза быстее? И еще вопросик, можно ли на лету сменить директорию с шаблонами? как сменить директорию в которую компилиится - в документации есть, хотя директория с шаблонами более нужная к смене вещь...

bzick commented 9 years ago

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


class MyProvider extends Fenom\Provider {
    public function setTemplateDir($dir) {
        $this->__construct($dir);
    }   
}

$provider = new MyProvider('./tpls/project_a');
$fenom = new Fenom($provider);
// ...

$provider->setTemplateDir('./tpls/project_b');

Этот вариант хорошо будет работать если Вас не устраивает несколько директорий одновременно.

$fenom = Fenom::factory('./tpls/shared');
$fenom->addProvider(new Fenom\Provider('a', './tpls/project_a'), '/tmp/a');
$fenom->addProvider(new Fenom\Provider('b', './tpls/project_b'), '/tmp/b');
{include "a:index.tpl"}  {*  это будет  ./tpls/project_a/index.tpl *}
{include "b:index.tpl"}  {*  это будет  ./tpls/project_b/index.tpl *}
{include "index.tpl"}  {*  это будет  ./tpls/shared/index.tpl *}
f0mich commented 9 years ago

1) А, понял. в приложенном примере по умолчанию включен Fenom::AUTO_RELOAD и основную задержку дает clearstatcache внутри Provider::getLastModified. если убрать функцию clearstatcache, то у меня время становиться 0.07-0.06, что уже ближе к чистому пыху. Если отключить параметр Fenom::AUTO_RELOAD - скорость тоже становиться 0.07-0.06. тестировал под виндой. Имхо полезность clearstatcache в шаблонизаторе не велика т.к. вероятность того что кто-то несколько раз за время работы скрипта обратиться к шаблону и после первого раза изменит этот шаблон - весьма мала и вот для такие экстрималов можно сделать дополнительный параметр (типа Fenom::clearstatecache), а вот задержку эту функция дает неплохую. Ну и как следствие параметр Fenom::AUTO_RELOAD можно смело убрать, так как на прозводительность (если убрать clearstatcache ) это вообще не влияет, а проверять изменение шаблонов на живом сайте нужно частенько. 2) Просто, например, у меня в системе есть модули, и каждый модуль берет шаблоны из своей директории. и хотелось бы чтоб они могли просто делать {include "block.tpl"} не задумываясь, как называется provider для этого модуля. было бы очень полезно по аналогии с setCompileDir получить функцию setTemplateDir

bzick commented 9 years ago

1) Отключил clearstatecache по умолчанию, но можно включить через метод провайдера. 2) Мало данных что бы понять что требуется. У вас два модуля не могут быть на одной странице? когда решается какой модуль будет использован в этот момент можно указать источник шаблонов?

f0mich commented 9 years ago

1) круть! я тут нашел еще пару слабых место. в Provider.php используеются realpath. у меня на ноуте (повторюсь - винда) эту функция занимает 10-20% от времяни показа шаблона. если она используется для совместимости слешей винда/линкус, то лучше использовать

str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->_path)

Если она используется для проверки существования файла - то она безполезна т.к. там в дальнейшем используется filemtime - и он выдаст ошибку если файла нету, и можно на нее вызывать тот эксепшен, который сейчас используется в _getTemplatePath. да и вобщем саму функцию можно убрать тогда т.к. она становиться не особо нужной... второе место это Fenom.php в функии _load функция is_file сжирает те же 10-20% (покрайней мере в винде). смысл, опять же, не очень ясный, можно инклудить в слепую и потом обрабатывать ошибки через set_error_handler, если что-то пошло не так. после того как я заменил эти две вещи у себя - время выполнения чистого пыха+filemtime и время фенома практически сравнялись! предлагаю внести эти изменения и попробовать прогнать феномовский бенчмарк.... 2) ладно, пока не знаю как это объяснить чтоб понятно было. пока сделаю для себя обертку, потом может еще помучую немного :)

bzick commented 9 years ago

Да, есть такое дало. И у меня и travis-ci нет винды,поэтому протестировать Fenom под виндой у меня всегда вызывает сложности.

f0mich commented 9 years ago

ну впринципе на линухе операции с файлами тоже занимают время, хотя и меньше конечно, у меня на серваке core i7 обращение к одному файлу занимаеть 0.00007 так что тоже лучше избегать лишней работы с файлами, если такая возможность есть...

bzick commented 9 years ago

по поводу DIRECTORY_SEPARATOR. я предпочитаю что бы задавали пути уже с нужными слешами, если так нужен обратный слеш. Адаптироваться под винду немного не целесообразно ибо она почти всегда используется для разработки, где производительность не играет роли (это одна из причин почему я не проверяю производительность под виндой). На бою как правило nix системы, где как раз и надо стараться выжимать максимум. Поэтому лишние str_replace не хотелось бы городить. Так же в nix системах есть mmap который ускоряет во много крат повторное обращение к файлу. И да, внутри PHP очень много костылей для винды, не удивительно что php тупит там :) по поводу realpath. Эту функцию я использую для того что-бы канонизировать путь из /path/.././to/.././/template.tpl в /path/to/template.tpl (что бы нельзя было выйти за разрешенную директорию шаблонов), так же она проверяет наличие файла автоматически. Реализованный свой метод на регулярках и условиях оказался медленнее чем realpath() по поводу is_file и filemtime. Провайдеры и движок изолированные друг от друга так как провайдер может быть написан индивидуально под проект и движок доверять ему не может, поэтому у движка есть is_file(), а у провайдера filemtime(). Самый частый вариант провайдера который тянет шаблоны из бд. Там, конечно, нет никаких filemtime() и работает быстрее фс в некоторых случаях.

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

bzick commented 9 years ago

Постарался убрать лишние обращения к фс