php 无侵入的性能分析:耗时、内存消耗、执行次数

2021-08-08  本文已影响0人  猿来是八阿哥
<?php

/**
 * Class Tracker
 * {"file":"tick.php","line":66,"type":"memory","diff":"32MB"}
 * {"file":"tick.php","line":70,"type":"time","diff":"1s"}
 * {"file":"tick.php","line":76,"type":"execution","times":10000}
 */
class Tracker{
    protected $executionLimit;
    protected $memoryLimit;
    protected $timeLimit;
    protected $timeStart;
    protected $memoryStart;
    protected $executionMap;
    protected $badSmells = [];

    public function __construct($executionLimit=100, $memoryLimit=1024*1024, $timeLimit=100){
        $this->executionLimit = intval($executionLimit);
        $this->memoryLimit = intval($memoryLimit);
        $this->timeLimit = intval($timeLimit);
        $this->memoryStart = memory_get_usage();
    }

    public function startTrack(){
        declare (ticks = 1);
        return ($this->timeLimit > 0 || $this->memoryLimit > 0 || $this->executionLimit > 0)
            && register_tick_function([$this, 'tickHook']);
    }

    public function terminalTrack(){
        if(!empty($this->badSmells)){
            foreach ($this->badSmells as $bs) {
                echo json_encode($bs).PHP_EOL;
            }
        }
    }

    public function tickHook(){
        $trace = debug_backtrace(1);
        $key = $trace[0]['file'].'_'.$trace[0]['line'];
        if($this->timeLimit > 0){
            $nowTime = microtime(1) * 1000;
            if($this->timeStart < 1){
                $this->timeStart = $nowTime;
            }else{
                $timeDiff = $nowTime - $this->timeStart;
                if($timeDiff >= $this->timeLimit){
                    $this->badSmells[$key.'_time'] = ['file'=>$trace[0]['file'], 'line'=>$trace[0]['line'], 'type'=>'time', 'diff'=>round($timeDiff/1000, 1).'s'];
                    $this->timeStart = 0;
                }
            }
        }
        if($this->memoryLimit > 0){
            $nowMemory = memory_get_usage();
            $memoryDiff = $nowMemory - $this->memoryStart;
            if($memoryDiff >= $this->memoryLimit){
                $this->badSmells[$key.'_memory'] = ['file'=>$trace[0]['file'], 'line'=>$trace[0]['line'], 'type'=>'memory', 'diff'=>round($memoryDiff/1024/1024, 1).'MB'];
            }
            $this->memoryStart = $nowMemory;
        }
        if($this->executionLimit > 0){
            $this->executionMap[$key]++;
            if($this->executionMap[$key] >= $this->executionLimit){
                $this->badSmells[$key.'_execution'] = ['file'=>$trace[0]['file'], 'line'=>$trace[0]['line'], 'type'=>'execution', 'times'=>$this->executionMap[$key]];
            }
        }
    }
}

function f1_memory($n){
    $data = array_fill(0, $n, 0);
}

function f2_time(){
    sleep(1);
}

function f3_execute(){
    $sum = 0;
    for($i=0; $i<10000; $i++){
        $sum += $i;
    }
    return $sum;
}
$tracker = new Tracker();
$tracker->startTrack();

f1_memory(1000000);
f2_time();
f3_execute();

$tracker->terminalTrack();

上一篇下一篇

猜你喜欢

热点阅读