Новый тест производительности pdoTools + Fenom

Как-то раз я уже тестировал pdoTools и писал об этом в своем блоге. Тогда причиной послужило то, что в описании этого компонента был размещен скриншот одного комментария от какого-то пользователя, где он писал, что скорость по сравнению с getProducts у него получилась в 5(!!!) раз выше. Но на проверку это оказалось дезинформацией и после уговоров администрации modx.pro тот скриншот всё-таки убрали.

К сожалению, статья утеряна вместе с другими статьями моего старого блога (авария на сервере), поэтому я решил снова проверить так ли быстр pdoTools, как заявляет автор. Тем более очень часто на форуме вижу как люди пишут про феноминальную скорость pdoTools + Fenom.
Главной задачей данного теста была проверка скорости работы парсера.

Я создал два тестовых сайта:
http://test.wdevblog.net.ru/test1/index.php?id=1
http://test.wdevblog.net.ru/test2/index.php?id=1


Результаты (средние цифры):

PHP 5.6

getProducts + getPage (стандартный парсер MODX)

Parse Time: 0.2122 s
Total Time: 0.2204 s
Source: database
Memory: 6.5 mb

pdoTools + Fenom

Parse Time: 0.2167 s
Total Time: 0.2273 s
Source: database
Memory: 13 mb

PHP 7.0 (сейчас на сервере эта версия)

getProducts + getPage (стандартный парсер MODX)

Parse Time: 0.0526 s
Total Time: 0.0572 s
Source: database
Memory: 2 mb

pdoTools + Fenom

Parse Time: 0.0359 s
Total Time: 0.0474 s
Source: database
Memory: 2 mb

Если пощелкаете переход по страницам, то результаты будут каждый раз немного отличаться, но в целом существенной разницы скорости работы парсера нет - PHP 5.6
У pdoTools на PHP 5.6 больше расход оперативной памяти (в 2 раза).
На число запросов к БД лучше не обращать внимания, т.к. эта цифра скорее всего не верная.

Обновлено
Добавил цифры для PHP 7.0. Картина для pdoTools + Fenom более красивая, но не очень существенно (~17%).


Шаблоны и чанки.

getProducts + getPage

Шаблон страницы

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/favicon.ico">

    <title>MODX Test site</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
    <style>
    body { padding-top: 5rem; }
    .starter-template { padding: 3rem 1.5rem; text-align: center; }
    </style>
    
  </head>

  <body>

    <main role="main" class="container">

<h1>getProducts + getPage</h1>
    
<div class="row">
[[!getPage?
&elementClass=`modSnippet`
&element=`getProducts`
&parents=`2`
&includeTVs=`1`
&includeTVList=`tv1,tv2,tv3,tv4`
&limit=`20`
&tpl=`sample_item`
&pageNavTpl=`<li class="page-item"><a class="page-link" href="[[+href]]">[[+pageNo]]</a></li>`
&pagePrevTpl=`<li class="page-item"><a class="page-link" href="[[+href]]">&laquo;</a></li>`
&pageNextTpl=`<li class="page-item"><a class="page-link" href="[[+href]]">&raquo;</a></li>`
&pageActiveTpl=`<li class="page-item active"><a class="page-link" href="[[+href]]">[[+pageNo]]</a></li>`
&pageFirstTpl=` <li class="page-item"><a class="page-link" href="[[+href]]">Первая</a></li> `
&pageLastTpl=` <li class="page-item"><a class="page-link" href="[[+href]]">Последняя</a></li> `
]]
</div>

<br class="clear" />
<ul class="pagination">
[[!+page.nav]]
</ul>


<div class="card card-body my-3 bg-secondary text-white" style="width: 300px; position: fixed; bottom: 15px; right: 15px; z-index: 1000;">
<div>Query Time: [^qt^]</div>
<div>Query Count: [^q^]</div>
<div>Parse Time: [^p^]</div>
<div>Total Time: [^t^]</div>
<div>Source: [^s^]</div>
<div>Memory: [[!ShowMemory]]</div>
</div>
    
    </main>
    
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>

  </body>
</html>

Чанк "sample_item"

<div class="col-12">
    <div class="card card-body mb-3">
    
        <h5>[[+pagetitle:ucase]] - ID = [[+id]]</h5>
        
        <div>
        [[+tv.tv1:is=`1`:then=`
             tv.tv1 ([[+tv.tv1]]) = 1
        `:else=`
             tv.tv1 ([[+tv.tv1]]) != 1
        `]]
        </div>
        
        <div>
        [[+pagetitle:contains=`Док`:then=`
            Название ([[+pagetitle]]) содержит "Док"
        `:else=`
            Название ([[+pagetitle]]) не содержит "Док"
        `]] 
        </div>
        
        <div>
        [[+tv.tv2:lt=`5`:then=`
             tv.tv2 ([[+tv.tv2]]) < 5
        `:else=`
             tv.tv2 ([[+tv.tv2]]) >= 5
        `]]
        </div>
        
        <div>
        [[+tv.tv3:in=`3,4,5,6`:then=`
             tv.tv3 ([[+tv.tv3]]) в массиве "3,4,5,6"
        `:else=`
             tv.tv3 ([[+tv.tv3]]) не в массиве "3,4,5,6"
        `]]
        </div>
        
        <div>
        Вложенные условия (два уровня):<br>
        [[+tv.tv4:gt=`4`:then=`
            tv.tv4 ([[!+tv.tv4]]) > 4<br>
            [[+tv.tv4:lt=`30`:then=`tv.tv4 ([[+tv.tv4]]) < 30`:else=`tv.tv4 ([[+tv.tv4]]) >= 30`]]
        `:else=`
             tv.tv4 ([[!+tv.tv4]]) <= 4<br>
            [[+tv.tv4:gt=`0`:then=`tv.tv4 ([[+tv.tv4]]) > 0`:else=`tv.tv4 ([[+tv.tv4]]) <= 0`]]
        `]]
        </div>
        
    </div>
</div>

pdoTools + Fenom

Шаблон страницы

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/favicon.ico">

    <title>MODX Test site</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
    <style>
    body { padding-top: 5rem; }
    .starter-template { padding: 3rem 1.5rem; text-align: center; }
    </style>
    
  </head>

  <body>

    <main role="main" class="container">

<h1>pdoTools + Fenom</h1>
    
<div class="row">
{$_modx->runSnippet('!pdoPage', [
    'element' => 'pdoResources',
    'parents' => 2,
    'depth' => 0,
    'tpl' => 'sample_item',
    'limit' => 20,
    'sortby' => 'id',
    'includeTVs' => 'tv1,tv2,tv3,tv4',
    'tvPrefix' => 'tv_',
    'prepareTVs' => 0,
    'processTVs' => 0,
    'tplPage' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">{$pageNo}</a></li>'
    'tplPageActive' => '@INLINE <li class="page-item active"><a class="page-link" href="{$href}">{$pageNo}</a></li>'
    'tplPagePrev' => '@INLINE <li class="page-item"><a class="page-link" href="[[+href]]">&laquo;</a></li>'
    'tplPageNext' => '@INLINE <li class="page-item"><a class="page-link" href="[[+href]]">&raquo;</a></li>'
    'tplPageFirst' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">Первая</a></li>'
    'tplPageLast' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">Последняя</a></li>'
    'tplPagePrevEmpty' => ''
    'tplPageNextEmpty' => ''
    'tplPageFirstEmpty' => ''
    'tplPageLastEmpty' => '',
    'showLog' => 0
])}
</div>

<br class="clear" />
<ul class="pagination">
{$_modx->getPlaceholder('page.nav')}
</ul>


<div class="card card-body my-3 bg-secondary text-white" style="width: 300px; position: fixed; bottom: 15px; right: 15px; z-index: 1000;">
<div>Query Time: [^qt^]</div>
<div>Query Count: [^q^]</div>
<div>Parse Time: [^p^]</div>
<div>Total Time: [^t^]</div>
<div>Source: [^s^]</div>
<div>Memory: {$_modx->runSnippet('!ShowMemory')}</div>
</div>
    
    </main>
    
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>

  </body>
</html>

Чанк "sample_item"

<div class="col-12">
    <div class="card card-body mb-3">
    
        <h5>{$pagetitle|upper} - ID = {$id}</h5>
        
        <div>
        {if $tv_tv1 == 1}
             tv.tv1 ({$tv_tv1}) = 1
        {else}
             tv.tv1 ({$tv_tv1}) != 1
        {/if}
        </div>
        
        <div>
        {if 'Док' in string $pagetitle}
            Название ({$pagetitle}) содержит "Док"
        {else}
            Название ({$pagetitle}) не содержит "Док"
        {/if}
        </div>
        
        <div>
        {if $tv_tv2 < 5}
             tv.tv2 ({$tv_tv2}) < 5
        {else}
             tv.tv2 ({$tv_tv2}) >= 5
        {/if}
        </div>
        
        <div>
        {if $tv_tv3 in list [3,4,5,6]}
             tv.tv3 ({$tv_tv3}) в массиве "3,4,5,6"
        {else}
             tv.tv3 ({$tv_tv3}) не в массиве "3,4,5,6"
        {/if}
        </div>
        
        <div>
        Вложенные условия (два уровня):<br>
        {if $tv_tv4 > 4}
            tv.tv4 ({$tv_tv4}) > 4<br>
            {if $tv_tv4 < 30}
                tv.tv4 ({$tv_tv4}) < 30
            {else}
                tv.tv4 ({$tv_tv4}) >= 30
            {/if}
        {else}
             tv.tv4 ({$tv_tv4}) <= 4<br>
             {if $tv_tv4 > 0}
                tv.tv4 ({$tv_tv4}) > 0
            {else}
                tv.tv4 ({$tv_tv4}) <= 0
            {/if}
        {/if}
        </div>
        
    </div>
</div>

Добавил цифры для PHP 7.0. Картина для pdoTools + Fenom более красивая, но не очень существенно (~17%).

Более усложненный вариант. 3 вызова сниппета на странице по 20 элементов.

PHP 7.0

getProducts + getPage

Parse Time: 0.1684 s
Total Time: 0.1760 s
Source: database
Memory: 2 mb

pdoTools + Fenom

Parse Time: 0.0849 s
Total Time: 0.1043 s
Source: database
Memory: 2 mb

Хороший результат у pdoTools + Fenom.

хм, на сложных сайтах действительно прирост почти в 2 раза. Недурно. Но, признаюсь, работал с pdoTppls + Fenom, не понравилось:

  1. Тащить зоопарк, который, если объективно, делает из modx совсем другую систему... Ну такое.
  2. Крайне хреново работает парсер. Тег {ignore} не работает как таковой. Хочешь JS на странице - занимайся любовью с выставлением пробелов перед фигурной скобкой.
  3. Если смешивать феном и стандартный синтаксис, то скорость получается нестабильной. Об этом даже сам Василий писал. А на старых проектах это будет всяко + многие дополнения не перешли на феном. Т.е. эта смесь будет всегда.

Короче, жутко на любителя тема.

@pooding в точку

Похоже, подключение к Форум | MODX Shopkeeper было разорвано, подождите, пока мы пытаемся восстановить соединение.