webspark / profiling-php
PHP项目的轻量级性能分析包。
Requires
- php: ^7.4|^8.0|^8.1|^8.2|^8.3
- ext-json: *
Requires (Dev)
- pestphp/pest: 2.34.7
- pestphp/pest-plugin-type-coverage: 2.8.1
README
导航
介绍
本软件包提供轻量级PHP性能分析器,用于速度和时间分析。它可以用来测量代码执行时间以及代码部分所花费的时间。这有助于找到代码中的瓶颈并进行优化。
软件包提供两种类型的分析:
- 速度分析 - 测量代码执行时间。
- 时间分析 - 测量代码部分的时间。
软件包易于使用,配置简单。它可以用于任何PHP项目。
工作原理
工作原理 - 速度分析。
使用SpeedProfiler
进行分析是基于使用析构函数作为动作的结束点。分析代码执行速度从SpeedProfiler
新实例的初始化开始,并在实例从RAM中清除时结束。在PHP中,析构函数在内存清除时自动调用,而内存清除发生在进程退出方法且方法中的变量不再需要处理代码时。
工作原理 - 时间分析。
时间分析基于使用Server-Timing
头部,该头部被浏览器识别并可显示为可读形式。这允许在浏览器中直接进行实时分析。
安装
您可以通过composer安装此软件包
composer require webspark/profiling-php
注意:由于提供者单例实现,性能分析器不能用于多线程过程。
配置
1. 处理器。
默认情况下,速度分析器将使用InMemoryProfilingProcessor
收集分析日志。这将为您提供当前页面加载的性能分析统计信息。
要收集所有动作的历史日志,您需要创建自己的处理器或使用我们提出的处理器。您可以使用DailyLogProfilingProcessor
将分析日志存储在每日日志文件中。每日日志处理器已实现日志文件轮换,默认值为7天。
注意:处理器仅用于速度分析。
要设置自定义处理器,您需要在提供者中设置它
SpeedProfilingProvider::getInstance()
->setProcessor(new DailyLogProfilingProcessor(<set log file name>, <set log file folder>, <set rotation days>));
2. 性能分析配置。
默认情况下,我们使用耗时超过1秒(1000毫秒)的操作进行性能分析。您可以通过设置自定义配置对象来覆盖性能分析配置。
SpeedProfilingProvider::getInstance()
->setConfig(new ProfilingConfig(['latency' => '2000'])); // to set latency in milliseconds
TimingsProfilingProvider::getInstance()
->setConfig(new ProfilingConfig(['latency' => '2000'])); // to set latency in milliseconds
使用
速度分析。
速度分析是一个有用的工具,可以查看代码执行所需时间。您可以存储测量结果在日志文件中并检查执行统计信息。
1. 速度分析全局操作。
要添加全局操作性能分析,您应在应用程序的入口点顶部添加new SpeedProfiler()
。它将为您的项目中的每个请求启动速度分析。例如在index.php中
require_once __DIR__ . '/vendor/autoload.php';
$profiler = new SpeedProfiler('Index action');
... // project logic
exit;
2. 特定位置的速度分析。
要记录特定的方法,您需要在方法的开始处创建一个SpeedProfiler
类的实例。当进程退出方法时,它将记录方法花费的时间。您可以在代码的任何地方使用它。
class Example
{
public function execute(): void
{
$profiler = new SpeedProfiler('Example execute action.');
... // some logic
}
}
3. 速度分析checkpoint
方法。
在记录时间的过程中,您可以使用SpeedProfiler
类的checkpoint
方法来记录方法的某些部分。此方法将记录从SpeedProfiler
初始化点开始的局部时间。
class Example
{
public function execute(): bool
{
$profiler = new SpeedProfiler('Example execute action.');
... // some logic
$profiler->checkpoint('First part of logic');
... // some logic
$profiler->checkpoint('Second part of logic');
... // some logic
return true; // method profiling finished
}
}
4. 速度分析统计。
分析统计有字段:max
- 所有已记录请求中的最大时间,avg
- 所有已记录操作请求的平均时间,med
- 所有已记录操作请求的中位数时间(不含最大执行时间和最小执行时间的10%),min
- 所有已记录操作请求中的最小时间,total
- 指定时间段内操作的总时间,call
- 已记录操作请求的数量,以及action
- 操作的名称。
要查看分析统计,您可以使用SpeedProfilerStatisticService
基于分析日志生成统计信息。您可以选择日期(默认所有已记录日期的格式为Y-m-d
),限制行数(默认为10)和排序(默认按最大时间排序)。
排序可以是:max(从较大的最大时间到较小的),min(从较大的最小时间到较小的),avg(从较大的平均时间到较小的),med(从较大的中位数时间到较小的),total(从较大的总时间到较小的)和calls(从较大的调用次数到较小的)。
$filters = new ProfilerStatisticFilters(
20, // by default is 10
date('Y-m-d'), //by default the all logged dates in format `Y-m-d`
new StatisticSortingType(StatisticSortingType::CALLS), //by default StatisticSortingType::MAX
);
$statisticList = (new SpeedProfilerStatisticService())->generate($filters);
时间分析。
时间分析是一个有用的工具,可以实时查看您的代码部分花费了多少时间。您可以在浏览器的网络部分查看测量结果。
要启用浏览器中的时间分析,您应在响应中添加带有服务器时间的头信息。您可以通过以下步骤实现:
1. 开始时间收集。
您需要在应用程序启动后开始自动时间收集。它将停止Bootstrap时间戳并开始App时间戳。例如在index.php中
require_once __DIR__ . '/vendor/autoload.php';
TimingsProfilingProvider::getInstance()->init();
... // project logic
默认情况下,您将有两个时间:Bootstrap
(框架初始化)和App
(从检测到路由操作到退出应用程序的时间)。我们将使用全局对象$_SERVER['REQUEST_TIME_FLOAT']
中的请求开始时间,您可以覆盖它。例如
TimingsProfilingProvider::getInstance()->init($requestStarted);
2. 在您的应用程序退出之前设置时间头信息。
要查看浏览器中的测量时间,您需要从提供者发送一个带有测量值的头信息。您可以在应用程序退出之前这样做。例如在index.php中
header(TimingsProfilingProvider::getInstance()->header());
3. 额外的时间测量。
要查看浏览器中的额外测量,您需要记录它们。我们有几种方法可以实现这一点。
- 使用
TimingsProfilingProvider
类。例如
public function execute(): void
{
TimingsProfilingProvider::getInstance()->start('Method execute');
... // some logic
TimingsProfilingProvider::getInstance()->stop('Method execute');
}
您也可以直接开始计时。它将在您请求提供者头信息时停止,并包括从起点开始的所有时间。例如
public function execute(): void
{
TimingsProfilingProvider::getInstance()->start('Execute');
... // some logic
}
- 使用
TimingsProfilingProvider
中的setDuration
方法。此方法将使用给定的时间记录测量。如果已存在具有该名称的计时测量,它将增加现有持续时间。更好的使用场景是测量重复操作,如数据库查询花费的时间。它将增加之前完成的测量。例如
$startPoint = microtime(true);
... // some logic
TimingsProfilingProvider::getInstance()
->setDuration('Measurement', (microtime(true) - $startPoint) * 1000);
您也可以提供回调而不是持续时间值,以测量回调的执行时间。例如
TimingsProfilingProvider::getInstance()
->setDuration('Timing name', static function () {
... // some logic here
});
- 使用
TimingsProfiler
类添加您的计时 - 它将在分析器析构时停止测量,当脚本离开方法时。例如
class Example
{
public function execute(): void
{
$profiler = new TimingsProfiler('Method execute');
... // some logic
}
}
所有计时也会在速度分析日志中显示 - 这对于了解长期操作代码部分花费了多少时间非常有帮助。
测试
执行测试
composer test
带有覆盖率的执行测试
composer test-coverage
变更日志
有关最近更改的更多信息,请参阅变更日志。
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。