Изначально профилируйте несколько сценариев в PHP7


С момента выпуска PHP 7 теперь невозможно профилировать весь набор сценариев с помощью declare(ticks=1) в вашем базовом файле, а затем с помощью register_tick_function() отслеживать каждый тик, поскольку он больше не следует путям включения. Согласно ошибке PHP, поданной по адресу https://bugs.php.net/bug.php?id=71448 это никогда больше не будет доступно в PHP 7.

Из-за ошибки реализации директива declare(галочки=1) просочилась в разные блоки компиляции до PHP 7.0. Это не так предполагается, что директивы declare(), которые предназначены для каждого файла или для каждой области, должны работать.

Существуют ли какие-либо альтернативы этому подходу с использованием собственного PHP (не расширений C или pear и т. Д.), Которые доступны мне в PHP 7, Что позволит мне профилировать каждую функцию или файл, вызываемый при загрузке страницы, по крайней мере, получая подробную информацию о фактическом пути к файлу.

Мой первоначальный вопрос, который привел к обнаружению ошибки, можно найти по адресу Как избежать повторного объявления галочек в каждом файле в PHP 7, это теперь речь идет об альтернативных методах.

Author: Funk Forty Niner, 2017-06-10

1 answers

Один из распространенных способов сделать это без declare(ticks=1) - использовать профилировщик. Профилировщик заметит любой вызванный метод/функцию, загруженный файл и т. Д. И даже получит информацию о времени, чтобы вы могли не только сказать, какая функция была вызвана, когда и каким кодом и какие файлы были открыты, но и какая часть программы заняла сколько времени.

Хорошо известный профилировщик в PHP поставляется со знаменитым расширением Xdebug. Он также поставляется с отладчик:

Одним из преимуществ является то, что вам не нужно менять код для профилирования, вам просто нужно принять конфигурацию PHP, чтобы вы могли включать и выключать ее по мере необходимости (например, сеанс отладки/профилирования).

Область использования PHP (функция галочки)

В качестве обходного пути, не имеющего declare(ticks=1); в начале каждого файла (после #71448), это можно добавить "на лету" с помощью обертки потока на файл протокол (для файлов в локальной файловой системе, который является общим), который его вводит.

Это технически выполнимо путем создания оболочки потока, зарегистрированной в файловом протоколе, для выполнения стандартных операций ввода-вывода файлов. В этом POC (Gist на Github) показана минимальная реализация, демонстрирующая, что она работает для includes. Когда test.php выполняется и, несмотря на то, что other.php не содержит declare(ticks=1); в нем на диске, зарегистрированная функция tick вызывается на include как показывает печать обратных следов:

...
tick_handler() called
#0  tick_handler(1) called at [/home/hakre/stream-wrapper-default-files/test.php:18]
#1  tick_handler() called at [/home/hakre/stream-wrapper-default-files/other.php:2]
#2  include(/home/hakre/stream-wrapper-default-files/other.php) called at [/home/hakre/stream-wrapper-default-files/test.php:24]
...

Вывод генерируется из зарегистрированной функции тика (здесь: test.php ):

<?php
/**
 * Inject declare ticks on include
 */
declare(ticks=1);

require __DIR__ . '/streamwrapper.php';

FileStreamWrapper::init();

// using a function as the callback
register_tick_function('tick_handler', true);


// Function which is called on each tick-event
function tick_handler()
{
    echo "tick_handler() called\n";
    debug_print_backtrace();
}

register_tick_function('tick_handler');

include "other.php";
include "another.php"; # file does not exists

Оболочка потока в примере gist реализована настолько мало, насколько это необходимо для работы с двумя операторами include, поскольку PHP-скрипты обычно выполняют больше операций ввода-вывода файлов, которые необходимо расширять по мере необходимости. Когда речь идет о поиске и т. Д., Необходимо учитывать динамическую вставку и т. Д., Но есть состояние для каждой файловой операции (дескриптор) поскольку на каждый экземпляр приходится по одному экземпляру, это должно быть хорошо инкапсулировано. Глобальное состояние используется для регистрации/отмены регистрации оболочки потока для каждой операции прокси-сервера в реальных функциях файловой системы, так как в противном случае это создает бесконечную рекурсию (оболочка использует оболочку, использует оболочку...). PoC до сих пор показывает, как это работает в принципе.

Это может быть (неправильно) использовано и для других целей, но этот PoC предназначен для ваших конкретных тиков объявления и включает прецедент.

 2
Author: hakre, 2017-06-19 00:01:32