duckstery/process-analyzer

PHP 无依赖进程分析器

1.0.2 2023-11-09 08:26 UTC

This package is auto-updated.

Last update: 2024-09-28 10:17:55 UTC


README

目录
  1. 特性
  2. 安装
  3. 配置
  4. 使用方法
  5. 测试
  6. 问题
  7. 许可

特性

  • 提供 Analyzer 以测量代码块的时间和内存量
  • 通过文件或控制台报告测量的数量
  • 支持多个配置文件和多个指标

例如,您可以这样做

// Start of code
$uid = Analyzer::start("Do a simple math");

// Calculating
$output = 1 + 1;
// Print output to screen
echo $output;

// End of code
Analyzer::stop($uid);
// Flush to get report
Analyzer::flush();

之后,您将获得这样的报告

Default --------------------
╭───────────────┬──────────────────┬─────────────┬────────┬────────────┬────────────┬───────────╮
│ Uid           │ Name             │ Time        │ Memory │ Start peak │ Stop peak  │ Diff peak │
├───────────────┼──────────────────┼─────────────┼────────┼────────────┼────────────┼───────────┤
│ 654af62889e08 │ Do a simple math │ 2006.472 ms │ 2.5 KB │ 16502872 B │ 16502872 B │       0 B │
╰───────────────┴──────────────────┴─────────────┴────────┴────────────┴────────────┴───────────╯
----------------------------

报告可以打印到文件或控制台。此外,您可以选择将报告结果捕获并打印到任何地方

安装

对于 PHP 8+

运行脚本进行安装

composer require --dev duckstery/process-analyzer

对于 Laravel

警告

此集成仅在处理单个请求时(每次一个请求)正常工作,因为它将在请求结束时清除所有内容。

运行脚本进行安装

composer require --dev duckstery/laravel-process-analyzer

包的 ServiceProvider 将自动由 Laravel 需要。如果您不使用自动发现,您需要手动将 ServiceProvider 添加到 config/app.php 中的 providers 数组

Duckstery\Laravel\Analyzer\ProcessAnalyzerServiceProvider::class

/*
    |--------------------------------------------------------------------------
    | Autoloaded Service Providers
    |--------------------------------------------------------------------------
    |
    | The service providers listed here will be automatically loaded on the
    | request to your application. Feel free to add your own services to
    | this array to grant expanded functionality to your applications.
    |
    */

    'providers' => ServiceProvider::defaultProviders()->merge([
        /*
         * Package Service Providers...
         */
        Duckstery\Laravel\Analyzer\ProcessAnalyzerServiceProvider::class, // ** //
        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
    ])->toArray(),

然后,您可以将配置文件发布以进行更好的自定义

php artisan vendor:publish --provider="Duckstery\Laravel\Analyzer\ProcessAnalyzerServiceProvider"

配置

如何配置

在开始使用之前,您应该配置软件包以满足您的需求。

要配置,创建一个类并扩展 AnalyzerConfig 如此

<?php

use Duckstery\Analyzer\AnalyzerConfig;

class MyAnalyzerConfig extends AnalyzerConfig
{
    // Todo
}

然后,您可以通过覆盖 AnalyzerConfig 的属性或函数并更改它们的值来自定义它们

<?php

use Duckstery\Analyzer\AnalyzerConfig;

class MyAnalyzerConfig extends AnalyzerConfig
{
    // Property override
    protected bool $prettyPrint;
    
    // Function override
    public function prettyPrint(): bool
    {
        return true;
    }
}

请注意,具有函数覆盖的配置将忽略属性值。如果您配置的逻辑很大,您应该使用函数覆盖。

创建配置类后,使用您的类的实例初始化 Analyzer

<?php

use Duckstery\Analyzer\Analyzer;

Analyzer::tryToInit(new MyAnalyzerConfig());

选项

enable:此选项将启用和禁用 Analyzer。使用此选项,您可以将此软件包包含在生产中。如果您需要在生产中测量您的进程,请将其打开。但请记住在之后将其关闭

  • 类型:     bool
  • 默认值:   true

defaultProfile:定义默认配置文件名

  • 类型:     string
  • 默认值:   "Default"

defaultRecordGetter:定义获取器方法名。此方法将返回记录的默认名称

  • 类型:     array | string | null
  • 默认值:  

profileExtras:为配置文件定义额外指标。这些指标可以在执行开始或结束时检索。之后,Analyzer 可以计算差异或格式化它们

  • 类型:     array
  • 默认值:  
[
    "Default" => [
        "peak" => [
            // Metrics method name's or callback array
            "handler" => "memory_get_peak_usage",
            // Formatter
            "formatter" => [Utils::class, "appendB"],
            // Get at the start
            "start" => true,
            // Get at the end
            "stop" => true,
            // Calculate difference
            "diff" => true
        ]
    ]
]

profile:配置文件类。您可以通过创建一个扩展 IAProfile 的新类来自定义

  • 类型:     string
  • 默认值:  
Duckstery\Analyzer\Structures\AnalysisProfile::class

record:记录类

  • 类型:     string
  • 默认值:  
Duckstery\Analyzer\Structures\AnalysisRecord::class

printer:打印机类

  • 类型:     string
  • 默认值:  
Duckstery\Analyzer\AnalysisPrinter::class

prettyPrint:以表格形式打印报告

  • 类型:     bool
  • 默认值:   true
  • 示例
$prettyPrint = true;
//    Default --------------------
//    ╭───────────────┬──────────────────┬─────────────┬────────┬────────────┬────────────┬───────────╮
//    │ Uid           │ Name             │ Time        │ Memory │ Start peak │ Stop peak  │ Diff peak │
//    ├───────────────┼──────────────────┼─────────────┼────────┼────────────┼────────────┼───────────┤
//    │ 654af62889e08 │ Do a simple math │ 2006.472 ms │ 2.5 KB │ 16502872 B │ 16502872 B │       0 B │
//    ╰───────────────┴──────────────────┴─────────────┴────────┴────────────┴────────────┴───────────╯
//    ----------------------------

$prettyPrint = false;
//    Default --------------------
//    [654af6159585c] Do a simple math:
//        Time ⇒ [2000.605 ms];
//        Memory ⇒ [2.5 KB];
//        Start peak ⇒ [16501872 B];
//        Stop peak ⇒ [16501872 B];
//        Diff peak ⇒ [0 B];
//    ----------------------------

oneLine:在报告中按行打印每个记录。如果 prettyPrint: true,则忽略

  • 类型:     bool
  • 默认值:  
  • 示例
$oneLine = true;
//    Default --------------------
//    [654b2b522090f] Do a simple math: Time ⇒ [2009.288 ms]; Memory ⇒ [2.5 KB]; Start peak ⇒ [16501904 B]; Stop peak ⇒ [16501904 B]; Diff peak ⇒ [0 B];
//    ----------------------------

$oneLine = false;
//    Default --------------------
//    [654af6159585c] Do a simple math:
//        Time ⇒ [2000.605 ms];
//        Memory ⇒ [2.5 KB];
//        Start peak ⇒ [16501872 B];
//        Stop peak ⇒ [16501872 B];
//        Diff peak ⇒ [0 B];
//    ----------------------------

showUID:在报告中显示记录的 UID

  • 类型:     bool
  • 默认值:   true

useFile:定义包含报告文件的目录的路径。每天将创建报告文件。如果 useFile 为 false,则报告不会打印到任何文件

  • 类型:     string
  • 默认值:   "logs"

useConsole:将结果打印到控制台。如果 useConsole 为 false,则报告不会打印到控制台

  • 类型:     bool
  • 默认值:   true

profilePrefix:定义配置文件名称的前缀

  • 类型:     string
  • 默认值:   ""

profileSuffix:定义配置文件名称的后缀

  • 类型:     string
  • 默认值:   ""

recordPrefix:定义记录名称的前缀

  • 类型:     string
  • 默认值:   ""

recordSuffix:定义记录的后缀

  • 类型:     string
  • 默认值:   ""

timeUnit:定义时间单位

  • 类型:     string
  • 默认值:   "ms"

timeFormatter:定义一个回调以修改主要时间指标。如果定义了此选项,则忽略timeUnit

  • 类型:     array | string | null
  • 默认值:   null

memUnit:定义内存单位

  • 类型:     string
  • 默认值:   "KB"

memFormatter:定义一个回调以修改主要内存指标。如果定义了此选项,则忽略memUnit

  • 类型:     array | string | null
  • 默认值:  

topLeftChar:定义左上角字符

  • 类型:     string
  • 默认值:   "╭"

topRightChar:定义右上角字符

  • 类型:     string
  • 默认值:   "╮"

bottomLeftChar:定义左下角字符

  • 类型:     string
  • 默认值:   "╰"

bottomRightChar:定义右下角字符

  • 类型:     string
  • 默认值:   "╯"

topForkChar:定义上叉字符

  • 类型:     string
  • 默认值:   "┬"

rightForkChar:定义右叉字符

  • 类型:     string
  • 默认值:   "┤"

bottomForkChar:定义下叉字符

  • 类型:     string
  • 默认值:   "┴"

leftForkChar:定义左叉字符

  • 类型:     string
  • 默认值:   "├"

crossChar:定义交叉字符

  • 类型:     string
  • 默认值:   "┼"

打印钩子

存在一些打印机钩子,允许您与报告数据进行交互。要使用这些钩子,创建一个类并扩展AnalysisPrinter

Duckstery\Analyzer\AnalysisPrinter::class

然后,重写方法如下

<?php

use Duckstery\Analyzer\AnalysisPrinter;
use Duckstery\Analyzer\Interfaces\IAProfile;

class MyPrinter extends AnalysisPrinter
{
    public function onPreprocessProfile(IAProfile $profile): void
    {
        // Todo
    }
}

这些是可以使用的钩子

onPreprocessProfile:在处理配置文件之前执行

  • 参数: IAProfile:可以在该钩子中修改配置文件

onPreprocessRecord:在处理每个记录之前执行

  • 参数: IARecord:可以在该钩子中修改记录

onEachPreprocessedRecord:在处理每个记录之后执行

  • 参数: array
  • 示例:没有配置文件额外信息
$example = [
    "uid" => "654af6159585c",
    "name" => "handle",
    "time" => "2000.605 ms",
    "memory" => "2.5 KB",
]
  • 示例:有配置文件额外信息(峰值)
$example = [
    "uid" => "654af6159585c",
    "name" => "handle",
    "time" => "2000.605 ms",
    "memory" => "2.5 KB",
    "start peak" => ..., // If start = true
    "stop peak" => ..., // If stop = true
    "diff peak" => ..., // If start = stop = diff = true
]

onEachRecordString:在将记录转换为字符串后执行

  • 参数: string

onPrintProfileString:在完成报告后执行

  • 参数: string:这是最终的报告
  • 注意:修改此选项不会更改您的文件或控制台结果。如果您想将报告发送到其他地方,您应该禁用useFileuseConsole并在该钩子中定义您的逻辑。

使用方法

以下是一些示例,指导您使用此软件包。您将获得一个静态类。

Duckstery\Analyzer\Analyzer::class

Analyzer将仅测量您执行的执行时间和内存。它将排除最终结果中的自我执行时间和内存。

基本方法是将您的逻辑放在startstop中。完成所有操作后,调用flush,以便分析器为您生成报告。

Laravel集成具有一个特定的中间件,将在请求结束时执行flush。因此,在您使用该集成时不需要flush。但在大多数情况下,您必须在程序末尾(或至少在您想要测量的过程的末尾)调用flush

对于任何未提及的情况,您可以向我询问更多细节。

基本

Analyzer仅测量您执行的执行时间和内存

<?php

use Duckstery\Analyzer\Analyzer;

public class SomeController
{
    public function handle(): void
    {
        // Use Profile: SomeController and start recording
        Analyzer::profile("SomeController")->start("handle");
        
        // Execute process A
        $this->processA();
        // Execute process B
        $this->processB();
        // Execute process C
        $this->processC();
        
        // Stop the latest recording of Profile
        Analyzer::profile("SomeController")->stop();

        // Flush
        Analyzer::flush("SomeController");
        // Or Analyzer::flush(); to flush all Profile
    }
    
    public function processA(): void
    {
        // Use Profile: SomeController and start recording
        Analyzer::profile("SomeController")->start("processA");
    
        // Use 5kb
        
        // Stop the latest recording of Profile
        Analyzer::profile("SomeController")->stop();
    }
    
    public function processB(): void
    {
        // Use Profile: SomeController and start recording
        Analyzer::profile("SomeController")->start("processA");
    
        // Use 0kb
        
        // Stop the latest recording of Profile
        Analyzer::profile("SomeController")->stop();
    }
    
    public function processC(): void
    {
        // Use Profile: SomeController and start recording
        Analyzer::profile("SomeController")->start("processA");
    
        // Executed for 5s
        
        // Stop the latest recording of Profile
        Analyzer::profile("SomeController")->stop();
    }
}

报告

SomeController --------------------
╭───────────────┬──────────┬─────────────┬────────╮
│ Uid           │ Name     │ Time        │ Memory │
├───────────────┼──────────┼─────────────┼────────┤
│ 654af62889e08 │ handle   │ 5036.472 ms │   5 KB │
│ 654af62889e09 │ processA │    6.472 ms │   0 KB │
│ 654af62889e10 │ processB │    6.472 ms │   5 KB │
│ 654af62889e11 │ processC │ 5000.472 ms │   0 KB │
╰───────────────┴──────────┴─────────────┴────────╯
------------------------------

使用默认配置文件名和额外指标

配置

$profileExtras = [
    "Default" => [
        "peak" => [
            // Metrics method name's or callback array
            "handler" => "memory_get_peak_usage",
            // Formatter
            "formatter" => [Utils::class, "appendB"],
            // Get at the start
            "start" => true,
            // Get at the end
            "stop" => true,
            // Calculate difference
            "diff" => true
        ]
    ]
]

使用默认配置文件捕获指标

<?php

use Duckstery\Analyzer\Analyzer;

public class SomeController
{
    public function handle(): void
    {
        $uid = Analyzer::start("SomeController::handle");
        // Or Analyzer::start("SomeController::handle");
        // Todo
        Analyzer::stop($uid);
        // Or Analyzer::stop();

        // Flush
        Analyzer::flush();
    }
}

报告

Default --------------------
╭───────────────┬────────────────────────┬─────────────┬────────┬────────────┬────────────┬───────────╮
│ Uid           │ Name                   │ Time        │ Memory │ Start peak │ Stop peak  │ Diff peak │
├───────────────┼────────────────────────┼─────────────┼────────┼────────────┼────────────┼───────────┤
│ 654af62889e08 │ SomeController::handle │ 2006.472 ms │   0 KB │ 16502872 B │ 16502872 B │       0 B │
╰───────────────┴────────────────────────┴─────────────┴────────┴────────────┴────────────┴───────────╯
----------------------------

使用默认记录名

使用默认记录名称捕获指标

<?php

use Duckstery\Analyzer\Analyzer;

public class SomeController
{
    public function handle(): void
    {
        $uid = Analyzer::start();
        // Or Analyzer::start();
        // Todo
        Analyzer::stop($uid);
        // Or Analyzer::stop();

        // Flush
        Analyzer::flush();
    }
}

报告

Default --------------------
╭───────────────┬──────────────────┬─────────────┬────────┬────────────┬────────────┬───────────╮
│ Uid           │ Name             │ Time        │ Memory │ Start peak │ Stop peak  │ Diff peak │
├───────────────┼──────────────────┼─────────────┼────────┼────────────┼────────────┼───────────┤
│ 654af62889e08 │ Function: handle │ 2006.472 ms │   0 KB │ 16502872 B │ 16502872 B │       0 B │
╰───────────────┴──────────────────┴─────────────┴────────┴────────────┴────────────┴───────────╯
----------------------------

使用多个配置文件

使用多个配置文件捕获指标

<?php

use Duckstery\Analyzer\Analyzer;

public class SomeController
{
    public function handle(): void
    {
        $uid = Analyzer::startProfile("Profile 1");
        // Or Analyzer::startProfile("Profile 1");
        $this->todo();
        Analyzer::stopProfile("Profile 1", $uid);
        // Or Analyzer::stopProfile("Profile 1");

        // Flush
        Analyzer::flush();
    }
    
    public function todo(): void
    {
        $uid = Analyzer::startProfile("Profile 2");
        // Or Analyzer::startProfile("Profile 2");
        $this->todo();
        Analyzer::stopProfile("Profile 2", $uid);
        // Or Analyzer::stopProfile("Profile 2");
    }
}

报告

Profile 1 --------------------
╭───────────────┬──────────────────┬─────────────┬────────╮
│ Uid           │ Name             │ Time        │ Memory │
├───────────────┼──────────────────┼─────────────┼────────┤
│ 654af62889e08 │ Function: handle │ 2006.472 ms │   0 KB │
╰───────────────┴──────────────────┴─────────────┴────────╯
------------------------------
Profile 2 --------------------
╭───────────────┬────────────────┬─────────────┬────────╮
│ Uid           │ Name           │ Time        │ Memory │
├───────────────┼────────────────┼─────────────┼────────┤
│ 654af62889e09 │ Function: todo │ 2006.472 ms │   0 KB │
╰───────────────┴────────────────┴─────────────┴────────╯
------------------------------

测试

用于测试

composer run-script test

用于覆盖率

composer run-script test-coverage

问题

如果您发现任何与安全相关的问题、错误或想法,请随时创建一个问题。

许可

MIT许可证(MIT)。有关更多信息,请参阅许可证文件