Perfil nativo de múltiples scripts en PHP7

Desde el lanzamiento de PHP 7, ahora no es posible perfilar una selección completa de scripts utilizando declare(ticks=1) en su archivo base y luego usar register_tick_function() para monitorear cada tick ya que ya no incluye las rutas de acceso. De acuerdo con el error de PHP presentado en https://bugs.php.net/bug.php?id=71448, esto nunca volverá a estar disponible en PHP 7.

Debido a un error de implementación, la directiva declare (marca = 1) se filtró en diferentes unidades de comstackción antes de PHP 7.0. No es así como se supone que funcionen las directivas declare (), que son por archivo o por scope.

¿Existe alguna alternativa a este enfoque utilizando PHP nativo (no extensiones C o pera, etc.) que esté disponible para mí en PHP 7 y que me permita hacer un perfil de cada función o archivo llamado en una carga de página, obteniendo detalles de la ruta real del archivo? al menos.

Mi pregunta original que llevó a encontrar el error se puede encontrar en Cómo evitar la redeclarización de marcas en cada archivo en PHP 7 , esta pregunta ahora trata sobre métodos alternativos.

Una forma común de hacer esto sin declare(ticks=1) es usar un generador de perfiles. Un generador de perfiles tomará nota de cualquier método / función llamada, archivo cargado, etc. e incluso tomará información de tiempo para que no solo pueda decir qué función se llamó cuándo y con qué código y qué archivos se abrieron, sino también qué parte del progtwig tomó la forma. largo.

Un conocido generador de perfiles en PHP viene con la famosa extensión Xdebug . También se envía con un depurador:

Uno de los beneficios es que no necesita cambiar el código para hacer el perfilado, es solo la configuración de PHP que necesita adoptar para que pueda activarlo y desactivarlo cuando lo necesite (por ejemplo, sesión de depuración / perfilado).

PHP Userland (función de tick)

Como una alternativa no tener declare(ticks=1); al comienzo de cada archivo (después de # 71448 ), es posible agregar esto sobre la marcha a través de una envoltura de flujo en el protocolo de archivo (para archivos en el sistema de archivos local que es común) que lo inyecta.

Esto es técnicamente factible mediante la creación de una envoltura de flujo que se registra en el protocolo de archivo para las operaciones de e / s estándar de proxy. En este PoC (Gist on Github), se muestra la implementación mínima para demostrar que funciona para las inclusiones. Cuando se ejecuta test.php y, a pesar de eso, other.php no ha declare(ticks=1); en él, en el disco, se llama a la función de tick registrada en la inclusión, como muestra la impresión de los backtraces:

 ... 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] ... 

La salida se genera a partir de la función de marca registrada (aquí: test.php):

  

La envoltura de flujo en el ejemplo principal solo se ha implementado tan poco como sea necesario para trabajar con las dos declaraciones de inclusión, ya que los scripts de PHP normalmente hacen más archivos i / o que se deben ampliar según sea necesario. Cuando se trata de buscar, etc., se debe tener en cuenta la inserción dinámica, etc., pero hay un estado por operación de archivo (manejador) ya que hay una instancia por cada uno, por lo que este debe estar bien encapsulado. El estado global se utiliza para registrar / anular el registro de la envoltura de la ruta para cada operación de proxy en las funciones reales del sistema de archivos, de lo contrario, crea una recursión sin fin (la envoltura usa el envoltorio usa la envoltura ...). El PoC hasta ahora muestra cómo funciona en principio.

Esto también puede ser (mal) usado para otras cosas, pero este PoC es para sus marcas de statement específicas e incluye el caso de uso.