在PHP7中本机分析多个脚本 [英] Natively profile multiple scripts in PHP7

查看:58
本文介绍了在PHP7中本机分析多个脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自PHP 7发行以来,现在无法在基础文件中使用declare(ticks=1)来概要分析全部脚本,然后使用register_tick_function()监视每个刻度,因为不再遵循包含路径.根据 https://bugs.php.net/bug.php归档的PHP错误? id = 71448 ,它将在PHP 7中不再可用.

Since the release of PHP 7 it is now not possible to profile an entire selection of scripts using declare(ticks=1) in your base file and then using register_tick_function() to monitor each tick as it no longer follows include paths. According to the PHP bug filed at https://bugs.php.net/bug.php?id=71448 this will never be available again in PHP 7.

由于实现错误,在PHP 7.0之前,clarify(ticks = 1)指令泄漏到了不同的编译单元中.这不是按文件或按作用域的clarify()指令应该如何工作的.

Due to an implementation bug, the declare(ticks=1) directive leaked into different compilation units prior to PHP 7.0. This is not how declare() directives, which are per-file or per-scope, are supposed to work.

在使用PHP 7时,是否可以使用本机PHP(不是C或pear扩展名等)来替代此方法,这将使我能够对页面加载中调用的每个函数或文件进行配置,以获取详细信息.至少是实际文件路径.

Are there any alternatives to this approach using native PHP (not C or pear extensions etc.) that are available to me in PHP 7 that will allow me to profile each function or file called in a page load, getting details of the actual file path at least.

我的导致错误发现的原始问题可以在

My original question that led to finding the bug can be found at How to avoid redeclaring ticks on every file in PHP 7, this question is now about alternative methods.

推荐答案

在没有declare(ticks=1)的情况下执行此操作的一种常见方法是使用探查器.探查器将注意到任何方法/函数的调用,文件加载等,甚至获取时间信息,因此您不仅可以说出何时,通过什么代码以及打开了哪些文件而调用了哪个函数,而且还可以知道该程序的哪一部分花费了多长时间.

One common way to do this without declare(ticks=1) is to use a profiler. A profiler will take notice of any method/function called, file loaded etc. and even take timing information so you not only can say which function was called when and by what code and which files were opened but also which part of the program took how long.

PHP中著名的探查器随附了著名的 Xdebug扩展.它还带有调试器:

A well known profiler in PHP comes with the famous Xdebug extension. It also ships with a debugger:

一个好处是您不需要更改代码即可进行性能分析,它只是您需要采用的PHP配置,因此您可以根据需要将其打开和关闭(例如,调试/性能分析会话)

One benefit is that you don't need to change the code to do the profiling, it is just the PHP configuration you need to adopt so you can switch it on and off as you need it (e.g. debug / profiling session).

作为一种变通方法,每个文件的开头都没有declare(ticks=1);(在#71448 ),则可以通过 file 协议(适用于本地文件系统中常见的文件)上的流包装程序将其动态添加.注入它.

As a work-around not having declare(ticks=1); at the beginning of each file (after #71448), it is possible to add this on-the-fly via a stream-wrapper on the file protocol (for files in the local file-system which is common) that injects it.

这在技术上是可行的,方法是创建一个流包装器,该包装器在文件协议上注册以代理标准文件I/O操作.在此 PoC(Gist on Github)中,展示了最简单的实现,以证明其有效对于包括.当执行test.php并且尽管other.php在磁盘上没有declare(ticks=1);时,已注册的tick函数将在include上被调用,显示回溯轨迹:

This is technically feasible by creating a stream-wrapper that is registered on the file protocol to proxy standard file i/o operations. In this PoC (Gist on Github) the bare-minimum implementation is shown to demonstrate that it works for includes. When test.php is executed and despite that other.php has not declare(ticks=1); in it on disk, the registered tick function is called on the include as the print of the backtraces show:

...
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)生成的:

The output is generated from the registered tick function (here: 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

示例示例中的流包装器仅实现为这两个include语句所需的工作量很少,因为PHP脚本通常会处理更多的文件I/O,因此需要根据需要对其进行扩展.当进行查找等操作时,需要考虑动态插入等操作,但是每个文件操作(句柄)都有状态,因为每个实例都有一个实例,因此应该对其进行很好的封装.全局状态用于为每个操作注册/注销流包装器,以代理到实际的文件系统功能中,否则会产生无限递归(包装器使用包装器使用包装器...).到目前为止,PoC展示了它是如何工作的.

The stream wrapper in the gist example has only implemented as little as needed to work for the two include statements, as PHP scripts normally do more file i/o it needs to be extended as needed. When it goes about seeking etc., the dynamic insertion needs to be taken into account etc. but there is state per file operation (handle) as there is one instance per each one so this should be well encapsulated. The global state is used for registering/unregistering the stream wrapper for each operation to proxy into the real file-system functions as otherwise it creates endless recursion (wrapper uses the wrapper uses the wrapper ...). The PoC so far shows how it works on principle.

这也可以用于其他用途,但是此PoC用于您的特定声明滴答并包括用例.

This can be (mis-)used for other things as well, but this PoC is for your specific declare ticks and include use-case.

这篇关于在PHP7中本机分析多个脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆