Почему у меня не повышается производительность при использовании ClassMapAutoloader в Zend Framework 2?

В моей компании мы разрабатываем приложение ZF2, без программы ;-), прямо сейчас. Мы подошли к тому моменту, когда хотим протестировать часть приложения, опубликовав его на сайте www.

Мы подготовили STAGE-окружение, и сейчас я занимаюсь настройкой производительности. Я читал, что использование ClassMapAutoloader намного быстрее, чем StandardAutoLoader, как описано, например. http://samminds.com/2012/11/zf2-performance-quicktipp-2-classmap-autoloading/ . Я понимаю, почему это должно быть быстрее, но в моем случае я профилировал сайт с ClassMapAutoloader и без него, используя xdebug профилирование, WinCacheGring/QCacheGrind, и он медленнее примерно на 0,2%.

Кто-нибудь знает, почему это может быть медленнее?

Я использую CentOS и версию PHP => 5.6.12.

ИЗМЕНИТЬ ДОБАВЛЕННУЮ ИНФОРМАЦИЮ:

Пример одного autoload_classmap.php:

    <?php
// Generated by ZF2's ./bin/classmap_generator.php
return array(
    'Search\Elasticsearch\Document\AbstractDocument'          => __DIR__ . '/src/Search/Elasticsearch/Document/AbstractDocument.php',
    'Search\Elasticsearch\Document\ArticleDocument'           => __DIR__ . '/src/Search/Elasticsearch/Document/ArticleDocument.php',
    'Search\Elasticsearch\Document\BookingDocument'           => __DIR__ . '/src/Search/Elasticsearch/Document/BookingDocument.php',
    'Search\Elasticsearch\Document\DocumentType'              => __DIR__ . '/src/Search/Elasticsearch/Document/DocumentType.php',
    'Search\Elasticsearch\Document\InvoiceDocument'           => __DIR__ . '/src/Search/Elasticsearch/Document/InvoiceDocument.php',
    'Search\Elasticsearch\Document\OfficeDocument'            => __DIR__ . '/src/Search/Elasticsearch/Document/OfficeDocument.php',
    'Search\Elasticsearch\Document\OfficeMemberDocument'      => __DIR__ . '/src/Search/Elasticsearch/Document/OfficeMemberDocument.php',
    'Search\Elasticsearch\Document\ProductDocument'           => __DIR__ . '/src/Search/Elasticsearch/Document/ProductDocument.php',
    'Search\Elasticsearch\Document\ProfileDocument'           => __DIR__ . '/src/Search/Elasticsearch/Document/ProfileDocument.php',
    'Search\Elasticsearch\Document\RatingDocument'            => __DIR__ . '/src/Search/Elasticsearch/Document/RatingDocument.php',
    'Search\Elasticsearch\Document\AbstractWebSearchDocument' => __DIR__ . '/src/Search/Elasticsearch/Document/AbstractWebSearchDocument.php',
    'Search\Elasticsearch\AutoSuggestionQueryHandler'         => __DIR__ . '/src/Search/Elasticsearch/AutoSuggestionQueryHandler.php',
    'Search\Elasticsearch\SearchStatisticIndexHandler'        => __DIR__ . '/src/Search/Elasticsearch/SearchStatisticIndexHandler.php',
    'Search\Elasticsearch\TermRecognizerQueryHandler'         => __DIR__ . '/src/Search/Elasticsearch/TermRecognizerQueryHandler.php',
    'Search\Elasticsearch\SearchIndexHandler'                 => __DIR__ . '/src/Search/Elasticsearch/SearchIndexHandler.php',
    'Search\Elasticsearch\SearchQueryHandler'                 => __DIR__ . '/src/Search/Elasticsearch/SearchQueryHandler.php',
    'Search\Elasticsearch\TermRecognizerIndexHandler'         => __DIR__ . '/src/Search/Elasticsearch/TermRecognizerIndexHandler.php',
    'Search\Exception\Exception'                              => __DIR__ . '/src/Search/Exception/Exception.php',
    'Search\Factory\AutoSuggestQueryHandlerFactory'           => __DIR__ . '/src/Search/Factory/AutoSuggestQueryHandlerFactory.php',
    'Search\Factory\AutoSuggestServiceFactory'                => __DIR__ . '/src/Search/Factory/AutoSuggestServiceFactory.php',
    'Search\Factory\DocumentStorerServiceFactory'             => __DIR__ . '/src/Search/Factory/DocumentStorerServiceFactory.php',
    'Search\Factory\QueueWorkerServiceFactory'                => __DIR__ . '/src/Search/Factory/QueueWorkerServiceFactory.php',
    'Search\Factory\SearchIndexHandlerFactory'                => __DIR__ . '/src/Search/Factory/SearchIndexHandlerFactory.php',
    'Search\Factory\SearchQueryHandlerFactory'                => __DIR__ . '/src/Search/Factory/SearchQueryHandlerFactory.php',
    'Search\Factory\SearchServiceFactory'                     => __DIR__ . '/src/Search/Factory/SearchServiceFactory.php',
    'Search\Factory\SearchSimpleServiceFactory'               => __DIR__ . '/src/Search/Factory/SearchSimpleServiceFactory.php',
    'Search\Factory\SearchStatistikIndexHandlerFactory'       => __DIR__ . '/src/Search/Factory/SearchStatistikIndexHandlerFactory.php',
    'Search\Factory\TermRecognizerServiceFactory'             => __DIR__ . '/src/Search/Factory/TermRecognizerServiceFactory.php',
    'Search\Factory\TermrecognizerIndexHandlerFactory'        => __DIR__ . '/src/Search/Factory/TermrecognizerIndexHandlerFactory.php',
    'Search\Factory\TermrecognizerQueryHandlerFactory'        => __DIR__ . '/src/Search/Factory/TermrecognizerQueryHandlerFactory.php',
    'Search\Factory\RequestHandlerFactory'                    => __DIR__ . '/src/Search/Factory/RequestHandlerFactory.php',
    'Search\Logger\LoggerInterface'                           => __DIR__ . '/src/Search/Logger/LoggerInterface.php',
    'Search\Logger\StatisticLogger'                           => __DIR__ . '/src/Search/Logger/StatisticLogger.php',
    'DatabaseQueue'                                           => __DIR__ . '/src/Search/Queue/DatabaseQueue.php',
    'Search\Search\QueryWordReducer'                          => __DIR__ . '/src/Search/Search/QueryWordReducer.php',
    'Search\Search\RecognizedTermConsumer'                    => __DIR__ . '/src/Search/Search/RecognizedTermConsumer.php',
    'Search\Search\SearchService'                             => __DIR__ . '/src/Search/Search/SearchService.php',
    'Search\Search\SuggestionListBuilder'                     => __DIR__ . '/src/Search/Search/SuggestionListBuilder.php',
    'Search\Search\Util'                                      => __DIR__ . '/src/Search/Search/Util.php',
    'Search\Search\ViewState'                                 => __DIR__ . '/src/Search/Search/ViewState.php',
    'Search\Search\ViewStateToSearchRequestTransformer'       => __DIR__ . '/src/Search/Search/ViewStateToSearchRequestTransformer.php',
    'Search\Search\SearchSimpleService'                       => __DIR__ . '/src/Search/Search/SearchSimpleService.php',
    'Search\AutoSuggester'                                    => __DIR__ . '/src/Search/AutoSuggester.php',
    'Search\QueryCleaner'                                     => __DIR__ . '/src/Search/QueryCleaner.php',
    'Search\Request'                                          => __DIR__ . '/src/Search/Request.php',
    'Search\RequestHandler'                                   => __DIR__ . '/src/Search/RequestHandler.php',
    'Search\SearchSource'                                     => __DIR__ . '/src/Search/SearchSource.php',
    'Search\Util'                                             => __DIR__ . '/src/Search/Util.php',
    'Search\QueueWorker'                                      => __DIR__ . '/src/Search/QueueWorker.php',
    'Search\AbstractDocumentStorer'                           => __DIR__ . '/src/Search/AbstractDocumentStorer.php',
    'Search\DocumentStorer'                                   => __DIR__ . '/src/Search/DocumentStorer.php',
    'Search\TermRecognizer'                                   => __DIR__ . '/src/Search/TermRecognizer.php',
    'Search\Module'                                           => __DIR__ . '/Module.php',
);

Выдержка из соответствующего Module.php:

public function getAutoloaderConfig() {
    return [
        'Zend\Loader\ClassMapAutoloader' => [
            __DIR__ . '/autoload_classmap.php'
        ],
        'Zend\Loader\StandardAutoloader' => [
            'namespaces' => [
                __NAMESPACE__ => __DIR__ . '/src/' . str_replace('\\', '/', __NAMESPACE__)
            ]
        ]
    ];
}

Я уже проверил, что автозагрузчик использует карту классов.

ИЗМЕНИТЬ ДОБАВЛЕННУЮ ИНФОРМАЦИЮ: Панель инструментов разработчика Zend 1

Панель инструментов разработчика Zend 2

Панель инструментов разработчика Zend 3


person Gizzmo    schedule 18.08.2015    source источник
comment
Медленнее на сколько? Кроме того, профилирование xdebug предназначено для отладки проблем с производительностью, не используйте его для измерения производительности, так как это приводит к значительным накладным расходам и может исказить ваши результаты.   -  person Tim Fountain    schedule 18.08.2015
comment
Xdubug и webgrind значительно замедляют работу веб-сайта и должны использоваться только в процессе разработки. Покажите нам свой classmap_autoload.php и конфигурацию   -  person Stanimir Dimitrov    schedule 18.08.2015
comment
@stanimir: Конечно, я использую xdbug только в разработке ;-) извините за это недоразумение   -  person Gizzmo    schedule 19.08.2015
comment
@tim: я использовал xdebug, потому что я видел, что я не получаю никакой производительности => поэтому я решил профилировать с помощью xdebug, чтобы проверить, есть ли разница до и после изменения, я в основном использую эту процедуру, чтобы проверить результаты изменений в лучшей производительности   -  person Gizzmo    schedule 19.08.2015
comment
@Gizzmo Насколько велик Module.php?   -  person Stanimir Dimitrov    schedule 19.08.2015
comment
@Stanimir: Чаще всего у меня в проекте около 20 module.php, около 30 строк. Только 1 имеет около 120 строк кода.   -  person Gizzmo    schedule 19.08.2015
comment
Установите github.com/zendframework/ZendDeveloperTools с помощью github.com/bjyoungblood/BjyProfiler или github.com /doctrine/DoctrineORMModule и покажите мне изображение данных профилирования, чтобы я мог написать ответ. classmap_autoload.php — это лишь малая часть того, как сделать ZF быстрым.   -  person Stanimir Dimitrov    schedule 19.08.2015
comment
Я добавил несколько скриншотов; потому что я почти не использую какие-либо DB-запросы (пока только 1) в общедоступной области, я не устанавливал github.com/bjyoungblood/BjyProfiler, но я установил github.com/doctrine/DoctrineORMModule, надеюсь, это поможет.   -  person Gizzmo    schedule 20.08.2015
comment
Добавьте библиотеку Zend в свой autoload_classmap.php   -  person newage    schedule 21.08.2015


Ответы (1)


Извините за столь поздний ответ. Прямо сейчас ваше приложение загружается за полсекунды — 0,6 с, если быть точным. Так что я автозагрузчик делает свое дело. Ваши запросы также выполняются быстро. Я могу придумать еще два способа ускорить ваши приложения.

  • Первый способ - с помощью карты шаблона

Найдите файл templatemap_generator.php. Он должен быть в вашей папке vendor/zendframework/zendframework/bin. Перейдите в папку вашего модуля, например. Application, где находятся src, view, config папки. Откройте терминал и введите php ../../vendor/zendframework/zendframework/bin/templatemap_generator.php ZF создаст карту шаблонов в каталоге вашего модуля. Теперь, чтобы использовать этот шаблон, просто измените файл module.config.php. Структура файла аналогична структуре clasmap_autoloader.php.

return array(
// Telling where the views are
'view_manager' => array(
    'display_not_found_reason' => true,
    'display_exceptions'       => true,
    'doctype'                  => 'HTML5',
    'not_found_template'       => 'error/404',
    'exception_template'       => 'error/index',
    'template_map' => include __DIR__ . '/../template_map.php', // <-- add this line. You can remove `template_path_stack`
),

В ваших контроллерах для каждого действия добавьте шаблон представления. public indexAction() { $view = new ViewModel(); $view->setTemplate("приложение/индекс/индекс"); вернуть $ представление; }

  • Второй способ - использование кеша модулей в производственной среде.

Допустим, у вас есть эта строка в вашем .htaccess - SetEnv APPLICATION_ENV "development"

В вашем файле public/index.php, если вы еще не сделали что-то подобное, добавьте следующее:

/**
 * Set global ENV. Used for debugging
 */
if (isset($_SERVER['APPLICATION_ENV']) && $_SERVER["APPLICATION_ENV"] === 'development') {
    define("APP_ENV", 'development');
} else {
    define("APP_ENV", "production");
}

Это гарантирует, что у вас есть глобальная среда в вашем приложении, которая сообщает, включена или выключена отладка, и это поможет вам избежать СУХОГО кода. Теперь из корневой папки откройте config/application.config.php

<?php

$modules = [];

if (APP_ENV === 'development') {
    $modules[] = 'ZendDeveloperTools';
    $modules[] = 'BjyProfiler';
    $modules[] = 'SanSessionToolbar';
}

$modules[] = 'Application';
$modules[] = 'Admin';

return [
    // This should be an array of module namespaces used in the application.
    'modules' => $modules,

    // These are various options for the listeners attached to the ModuleManager
    'module_listener_options' => [
        // This should be an array of paths in which modules reside.
        // If a string key is provided, the listener will consider that a module
        // namespace, the value of that key the specific path to that module's
        // Module class.
        'module_paths' => [
            './module',
            './vendor',
        ],

        // An array of paths from which to glob configuration files after
        // modules are loaded. These effectively override configuration
        // provided by modules themselves. Paths may use GLOB_BRACE notation.
        'config_glob_paths' => [
            'config/autoload/{{,*.}global,{,*.}local}.php',
        ],

        // Whether or not to enable a configuration cache.
        // If enabled, the merged configuration will be cached and used in
        // subsequent requests.
        'config_cache_enabled' => (APP_ENV === 'production'),

        // The key used to create the configuration cache file name.
        'config_cache_key' => md5('app_config'),

        // Whether or not to enable a module class map cache.
        // If enabled, creates a module class map cache which will be used
        // by in future requests, to reduce the autoloading process.
        'module_map_cache_enabled' => (APP_ENV === 'production'),

        // The key used to create the class map cache file name.
        'module_map_cache_key' => md5('module_map'),
        // The path in which to cache merged configuration.
        'cache_dir' => dirname(__DIR__)."/data/cache",

        // Whether or not to enable modules dependency checking.
        // Enabled by default, prevents usage of modules that depend on other modules
        // that weren't loaded.
        'check_dependencies' => (APP_ENV !== 'production'),
    ],

    // Used to create an own service manager. May contain one or more child arrays.
    //'service_listener_options' => [
    //     [
    //         'service_manager' => $stringServiceManagerName,
    //         'config_key'      => $stringConfigKey,
    //         'interface'       => $stringOptionalInterface,
    //         'method'          => $stringRequiredMethodName,
    //     ],
    // )

   // Initial configuration with which to seed the ServiceManager.
   // Should be compatible with Zend\ServiceManager\Config.
   // 'service_manager' => [],
];

config_cache_* активирует и кеширует вашу конфигурацию маршрута, когда ваше приложение находится в рабочей среде. Все маршруты ваших модулей будут кэшироваться. Также, если веб-сайт находится в производстве, модули отладки не будут загружены. Вы можете заменить md5('app_config') чем угодно.

person Stanimir Dimitrov    schedule 23.08.2015
comment
Нет проблем для позднего ответа! Спасибо за ответ в любом случае. TemplateMap никак не увеличил производительность, но второй, кеширующий конфиг, повысил производительность. так что спасибо за это. - person Gizzmo; 25.08.2015
comment
Было бы неплохо, если бы вы приняли мой ответ. :) Кроме того, на рисунках выше я вижу, что ваш ввод-вывод использует ~ 30 МБ памяти, поэтому вам нужно копаться внутри вашего php-кода и улучшать его. Также, если вы используете php 5.5+, я предлагаю вам перейти на Zend 2.5.1. - person Stanimir Dimitrov; 25.08.2015
comment
Итак, ваш ответ мне помог, но почему автозагрузка по карте классов не улучшила производительность, до сих пор неизвестно. Я подожду некоторое время, чтобы узнать, может ли кто-нибудь дать мне еще один совет по поводу автозагрузки. После этого я отмечаю ваш ответ как принятый, потому что вы действительно пытались мне помочь :-) - person Gizzmo; 25.08.2015