29 апр. 2014 г., 18:25

modxSmarty - отключение modx-парсера и существенное ускорение

возникла идея — отключить modx-парсер вообще на тех страницах где он не нужен. и использовать исключительно возможности smarty. попутно появилась возможность работать с дебаггером smarty.
я недавно вникаю в разработку на modx, поэтому мое решение наверняка крайне кривое — просьба просто его рассмотреть, и наставить на путь истиный. может кто-то сможет сделать более правильно и добавить в следующую версию пакета.
по результатам экспериментов рендеринг страниц без modx-парсера ускоряется очень существенно.
вот некоторые результаты: обычный вывод через modx-парсер:
mbpv:~ info$ ab -n 100 -c 4 www.na.ru/tyres/manufacturers/Nokian/Hakka_Z/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net/ Licensed to The Apache Software Foundation, www.apache.org/
Benchmarking www.na.ru (be patient).....done
Server Software: Apache/2.2.23 Server Hostname: www.na.ru Server Port: 80
Document Path: /tyres/manufacturers/Nokian/Hakka_Z/ Document Length: 17622 bytes
Concurrency Level: 4 Time taken for tests: 33.511 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Total transferred: 1809300 bytes HTML transferred: 1762200 bytes Requests per second: 2.98 [#/sec] (mean) Time per request: 1340.421 [ms] (mean) Time per request: 335.105 [ms] (mean, across all concurrent requests) Transfer rate: 52.73 [Kbytes/sec] received
Connection Times (ms) min mean[±sd] median max Connect: 0 0 1.0 0 10 Processing: 293 1338 354.8 1430 1902 Waiting: 284 1303 348.9 1390 1870 Total: 293 1338 355.0 1431 1902
Percentage of the requests served within a certain time (ms) 50% 1431 66% 1493 75% 1529 80% 1549 90% 1680 95% 1762 98% 1900 99% 1902 100% 1902 (longest request)
вывод с отключенным modx-парсером (при это НЕ кешируются ресурсы и шаблоны!):
mbpv:~ info$ ab -n 100 -c 4 www.na.ru/tyres/manufacturers/Nokian/Hakka_Z/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net/ Licensed to The Apache Software Foundation, www.apache.org/
Benchmarking www.na.ru (be patient).....done
Server Software: Apache/2.2.23 Server Hostname: www.na.ru Server Port: 80
Document Path: /tyres/manufacturers/Nokian/Hakka_Z/ Document Length: 14050 bytes
Concurrency Level: 4 Time taken for tests: 5.860 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Total transferred: 1452100 bytes HTML transferred: 1405000 bytes Requests per second: 17.07 [#/sec] (mean) Time per request: 234.394 [ms] (mean) Time per request: 58.599 [ms] (mean, across all concurrent requests) Transfer rate: 242.00 [Kbytes/sec] received
Connection Times (ms) min mean[±sd] median max Connect: 0 0 0.1 0 1 Processing: 81 232 80.1 238 376 Waiting: 73 214 74.7 220 349 Total: 81 233 80.2 239 377
Percentage of the requests served within a certain time (ms) 50% 239 66% 279 75% 307 80% 313 90% 336 95% 353 98% 361 99% 377 100% 377 (longest request) mbpv:~ info$
если включить кеширование шаблона — еще ускорится. в общем — очень быстро работает :)

как это сделано

Шаблон base.php:
<?php $properties = $modx->resource->getOne('Template')->getProperties(); if(!empty($properties['tpl'])){ $tpl = $properties['tpl']; } else{ $tpl = 'index.tpl'; } /* // управление кешем через галочку "кешируемый" у каждого ресурса // при этом будет работать modx=парсер каждый раз if ($modx->resource->cacheable != '1') { $modx->smarty->caching = false; } return $modx->smarty->fetch("tpl/{$tpl}"); */ // управление кешем через установку переменной caching = true; прямо тут в шаблоне. // при этом галочка "кешируемый" у ресурса игнорируется // и modx-парсер не работает! скорость генерации страницы растет ОЧЕНЬ существенно! // + можно использовать дебаггер //$modx->smarty->debugging=TRUE; $modx->smarty->caching = false; $modx->smarty->display("tpl/{$tpl}"); return ""; // отпрвить $ничего на вывод через modx-парсер. :)
modsmarty.class.php:
public function display($template, $cache_id = null, $compile_id = null, $parent = null) { echo $this->fetch($template, $cache_id, $compile_id, $parent); }
меняем на
public function display($template, $cache_id = null, $compile_id = null, $parent = null) { echo $this->fetch($template, $cache_id, $compile_id, $parent, true); }
честно говоря не понимаю кто оттуда убрал последний параметр — ибо в оригинальном класе он там был. хотя кажется я догадываюсь кто это сделал. но вот зачем — не понятно ибо эта функция как бы и не использовалась в шаблоне :)
собственно последний параметр true как раз и заставляет делать именно echo $_output;;, а не return $_output;
ну и чтобы заработал дебаггер делаем изменение в файле debug.tpl:
<table id="table_assigned_vars"> {foreach $assigned_vars as $vars} <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}"> <th>${$vars@key|escape:'html'}</th> <td>{$vars|debug_print_var}</td></tr> {/foreach} </table>
меняем на:
<table id="table_assigned_vars"> {foreach $assigned_vars as $vars} {if $vars@key != "modx"} <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}"> <th>${$vars@key|escape:'html'}</th> <td>{$vars|debug_print_var}</td></tr> {/if} {/foreach} </table>
это нужно чтобы не выводить объект modx который порушит дебаггер из-за переполнения памяти. ну или можно его вывести но как-то упрощенно.
вот такой эксперимент.
Добрый день!
Интересный эксперимент :) Но все же есть пара моментов. И вот основной:
$modx->smarty->display(«tpl/{$tpl}»); return ""; // отпрвить $ничего на вывод через modx-парсер. :)
Таким образом рушится механизм кеширования MODX, так как он не получает отрабатываемого контента. Ежели вы хотите именно отключить MODX-парсер, то есть более лаконичное решение — системная настройка parser_class. Она учитывается в методе MODx::getParser()
public function getParser() { return $this->getService('parser', $this->getOption('parser_class', null, 'modParser'), $this->getOption('parser_class_path', null, '')); }
То есть пишете парсер на замену modParser и все. А в нем, где надо, облегчаете методы по максимум, чтобы просто возвращали по минимуму и все.
Только вешайте его именно на внешний контекст, то есть в настройки контекста прописывайте, а не в системные, чтобы в mgr работал родной парсер, а во фронте ваш. Потому что системный парсер используется в том числе и для обработки системных настроек и т.п.
В общем, я решил тоже поучаствовать в этом эксперименте, и написать свой парсер на замену. Облегчить его на 100% не получается в любом случае. Во-первых, MODX довольно активно использует его отдельные методы, так что как минимум пустые методы надо прописать. Во-вторых, в тех же шаблонах у нас в параметрах есть необходимые параметры, типа tpl или phptemplates.non-cached, и чтобы они учитывались в системе, пришлось один метод более живым оставить. Вот такой класс у меня получился:
<?php class modWebParser { /** * A reference to the modX instance * @var modX $modx */ public $modx= null; /** * @param xPDO $modx A reference to the modX|xPDO instance */ function __construct(xPDO &$modx) { $this->modx =& $modx; } public function setProcessingElement($arg = null) { } public function processElementTags($parentTag, & $content, $processUncacheable= false, $removeUnprocessed= false, $prefix= "[[", $suffix= "]]", $tokens= array (), $depth= 0) { return $processed; } public function collectElementTags($origContent, array &$matches, $prefix= '[[', $suffix= ']]') { return 0; } /** * Parses an element/tag property string or array definition. * * @param string $propSource A valid property string or array source to * parse. * @return array An associative array of property values parsed from * the property string or array definition. */ public function parseProperties($propSource) { $properties= array (); if (!empty ($propSource)) { if (is_string($propSource)) { $properties = $this->parsePropertyString($propSource, true); } elseif (is_array($propSource)) { foreach ($propSource as $propName => $property) { if (is_array($property) && array_key_exists('value', $property)) { $properties[$propName]= $property['value']; } else { $properties[$propName]= $property; } } } } return $properties; } public function isProcessingUncacheable() { $result = false; return $result; } public function isRemovingUnprocessed() { $result = false; return $result; } public function parsePropertyString($string, $valuesOnly = false) { $properties = array(); return $properties; } }
Закинул его в core/components/modxsite/model/modxsite/model/modwebparser.class.php
В настройках контекста web прописал: parser_class = modWebParser parser_class_path = {core_path}components/modxsite/model/modxsite/
В целом все работает, и API MODX-а получается использовать, к примеру {$modx->getOption('site_url')}
Попробуйте установить ShopModxBox и погонять с этим парсером и без него. Но здесь надо учитывать, что многое не будет работать в принципе. Лично мне кажется, что овчинка не будет стоить выделки. К примеру, мы не сможем использовать некешируемые блоки через [[!smarty?tpl=`....`]] и т.п. Конечно же мы можем просто отрабатывать шаблоны каждый раз, включив кеширование самого Smarty, но это гораздо более заморочено.

Добавить комментарий