webspark / profiling-laravel
Lightweight profiling package for Laravel projects.
Requires
- php: ^7.4|^8.0|^8.1|^8.2|^8.3
- ext-json: *
- illuminate/support: 5.8.*|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0
- webspark/profiling-php: ^1.0.0
Requires (Dev)
- orchestra/testbench: 8.*
- pestphp/pest: 2.34.7
- pestphp/pest-plugin-type-coverage: 2.8.1
README
Navigation
Introduction
This package provides a lightweight PHP profiler for speed and timings profiling. It can be used to measure the time of your code execution and to see how much time it takes on your code parts. It can be useful to find bottlenecks in your code and to optimize it.
The package provides two types of profiling:
- Speed profiling - to measure the time of your code execution.
- Timings profiling - to measure the time of your code parts.
The package is easy to use and has a simple configuration. It can be used in any PHP project.
How it works
How it works Speed profiling.
Profiling with SpeedProfiler
is based on using a destructor as the end point of the action. Profiling of the code execution speed starts during the initialization of a new instance of SpeedProfiler
and ends when the instance is cleared from RAM. In PHP, the destructor is called automatically during memory clearing, and memory clearing occurs when the process exits a method and the variables in the method are no longer needed to process the code.
How it works Timings profiling.
Timing profiling is based on the use of the Server-Timing
header, which is recognized by the browser and can be displayed in a readable form. This allows real-time profiling directly in the browser.
Installation
You can install the package via composer:
composer require webspark/profiling-laravel
Configuration
1. Profiling configs.
You can override default configs by specifying them in your .env file:
PROFILING_SPEED_ENABLED={true|false}
PROFILING_SPEED_LATENCY={profiling latency in miliseconds}
PROFILING_TIMINGS_ENABLED={true|false}
PROFILING_TIMINGS_LATENCY={profiling latency in miliseconds}
2. Enable profiling.
To enable profiling you need to add ProfilingServiceProvider
to your providers list. After this you need to enable profiling in your .env file:
PROFILING_SPEED_ENABLED=true
PROFILING_TIMINGS_ENABLED=true
3. Processors.
By default, speed profiler will use InMemoryProfilingProcessor
to collect profiling logs. This will give you profiling statistics on the current page load. To collect historical logs of all actions you need to create your own processor or use one proposed by us. Your custom processor must implement an interface ProfilingProcessorInterface
.
You can use LogChannelProfilingProcessor
for storing profiling logs in a laravel log file. You need to provide laravel logging channel for processor constructor.
To use custom processor you need to override speed profiler registration in service provider:
class CustomProfilingServiceProvider extends ProfilingServiceProvider
{
protected function speedProfilingProcessor(): ProfilingProcessorInterface
{
return new LogChannelProfilingProcessor('daily');
}
}
Usage
Speed profiling.
Speed profiling is a useful tool to see how much time it takes on your code execution. You can store measurements in log files and check an execution statistic.
1. Speed profiling global actions.
To add global profiling you should add SpeedProfilingMiddleware
to your middlewares list. It will start speed profiling for every request to your project.
2. Speed profiling of specific places.
To record specific method you need to create an instance of SpeedProfiler
class at the start of this method. It will record the time spent on the method when process will exit out from the method. You can use it in any place of your code.
class Example
{
public function execute(): void
{
$profiler = new SpeedProfiler('Example execute action.');
... // some logic
}
}
3. Speed profiling checkoint
method.
In process of recording the time spent, you can record parts of the method with checkoint
method from the SpeedProfiler
class. This method will record partial time spent from the SpeedProfiler
initialisation point.
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. Speed profiling statistic.
Command output contains this fields: Max
- the largest time of all logged requests, Avg
- the average time of all logged action requests, Med
- the median time of all logged action requests without 10% from the max execution and 10% from the min execution, Min
- the smaller time of all logged action requests, Total
- total time spend on the action by the period, Call
- count of logged action requests and Action
- the name of action.
Max: 57.33 | Avg: 55.16 | Med: 52.32 | Min: 49.33 | Total: 4798.92 | Calls: 87 - App\Http\Controllers\Frontend\Auth\LoginController@login
Max: 17.28 | Avg: 15.21 | Med: 14.39 | Min: 13.19 | Total: 654.03 | Calls: 43 - App\Http\Controllers\Frontend\HomeController@index
Sorted by max
Artisan command name: profiling:speed-statistic
. You can specify date (by default the all logged dates are in format Y-m-d
), limit rows (by default is 10) and sorting (by default sorting by max time).
Sorting can be: max (from larger max time to smaller), min (from larger min time to smaller), avg (from larger avg time to smaller), med (from larger med time to smaller), total (from larger total time to smaller) and calls (from larger count of calls to smaller).
php artisan profiling:speed-statistic --sort=calls --limit=20 --date=2024-03-25
Timings profiling.
Timings profiling is a useful tool to see how much time it takes on your code parts. You can see measurement results in browser in network in section Timing.
1. Enable timings profiling.
To enable timings in browser you should add TimingsProfilingMiddleware
to your middlewares list.
By default, you will have that timings: Bootstrap
(framework initialisation), App
(time from route action was detected to exit from application) and Database
(how much time was spent on database queries).
All timings you will also have in speed profiler logs - it is helpful thing to understand how much time was taken on code parts for long term action.
2. Timing measurements.
To view an additional measurements in browser you need to record them. We have a few ways how to do it.
- Using the
TimingsProfiling
facade. For example:
public function execute(): void
{
TimingsProfiling::start('Method execute');
... // some logic
TimingsProfiling::stop('Method execute');
}
You also can just start timing. It will stop when you ask headers from provider and will include all time from starting point. For example:
public function execute(): void
{
TimingsProfiling::start('Method execute');
... // some logic
}
- Using methods
setDuration
fromTimingsProfiling
. This method will record measurement with given duration. If timing measurement with this name already exists, it will increment existed duration. The better place to use it is to measure repetitive actions, like time, that spent on database queries. It will increase previously finished measurements. For example:
$startPoint = microtime(true);
... // some logic
TimingsProfiling::setDuration('Measurement', (microtime(true) - $startPoint) * 1000);
You can also provide callback instead of duration value, to measure the execution time of the callback. For example:
TimingsProfiling::setDuration('Timing name', static function () {
... // some logic here
});
- Using
TimingsProfiler
class to add your timings - it will stop measurement on profiler destructor, when script leaves a method. For example:
class Example
{
public function execute(): void
{
$profiler = new TimingsProfiler('Method execute');
... // some logic
}
}
Testing
composer test
Execute tests with coverage:
composer test-coverage
Changelog
Please see CHANGELOG for more information on what has changed recently.
License
The MIT License (MIT). Please see License File for more information.