perftools / php-profiler

A PHP profiling library based on XHGUI Data Collector
MIT License
147 stars 26 forks source link

Provide preload.php to support PHP 7.4 / vendor profiling #54

Closed ScreamingDev closed 3 years ago

ScreamingDev commented 4 years ago

When using XHProf as composer package it is available after loading vendor/autoload.php . This makes it impossible to measure the impact of vendor-loading itself and also PHP 7.4 preloading can not be used in any way. Creating a preload.php with essential classes could solve the problem.

Example:

When writing a package that has some file loaded via composer

{
  "files": [
      "foo.php"
    ],
}

then XHProf needs to be available before Composers autoload.php to measure its impact. By now this can be done manually:

require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/ProfilerInterface.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/AbstractProfiler.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/XHProf.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/UProfiler.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/TidewaysXHProf.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profilers/Tideways.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/SaverFactory.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Saver/SaverInterface.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Saver/UploadSaver.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/ProfilerFactory.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/ProfilingFlags.php';
require_once __DIR__ . '/../vendor/perftools/php-profiler/src/Profiler.php';

(new \Xhgui\Profiler\Profiler( /* ... */ ))->start();

require_once __DIR__ . '/../vendor/autoload.php';

But it would be nice to have a preload.php in this repo ( https://github.com/perftools/php-profiler ) that loads all classes to allow measuring of vendor autoloads.

glensc commented 4 years ago

I don't believe preload everything being effective approach, even the doc says so:

https://www.php.net/manual/en/opcache.preloading.php:

Note that the optimal tradeoff between performance and memory may vary with the application. "Preload everything" may be the easiest strategy, but not necessarily the best strategy. Additionally, preloading is only useful when there is a persistent process from one request to another. That means while it can work in a CLI script if the opcache is enabled, it's generally pointless. The exception is when using preloading on FFI libraries.

You should create preload file specific to your application, with only files your application commonly uses.

And instead of doing require_once, you should be calling opcache_compile_file() for each of the files you wish to preload rather than requiring the files. this drops the need to include the files in a specific order (of dependencies) and saves memory as the files are only compiled, not loaded to memory.

see also discussions and opinions on this on composer issue tracker:

there's also a bug that versions up to 7.4.2 crash when using require in preload_file:

glensc commented 4 years ago

you can use perhaps this composer plugin to generate a preload file based on paths:

ScreamingDev commented 4 years ago

@glensc thanks for the hints on optimizing the preloading with "Ayesh/Composer-Preload".

The issue is about being able to start profiling before vendor/autoload.php . I assume that you pointed out "Ayesh/Composer-Preload" as a possible solution to this.

Does that mean that "perftools/php-profiler" will use "Ayesh/Composer-Preload" to provide a preload.php ?

So that anyone can monitor all the vendor performance like ...

<?php

require_once __DIR__ . '/../vendor/perftools/php-profiler/preload.php';
// or require_once __DIR__ . '/../vendor/preload.php';

(new \Xhgui\Profiler\Profiler( /* ... */ ))->start();

require_once __DIR__ . '/../vendor/autoload.php';

Edit: I would prefer the non-commented line to even measure all the pre-loads and other stuff that could happen.

glensc commented 4 years ago

okay, leaving aside PHP 7.4 preloading, providing autoload.php is what I can do.

ScreamingDev commented 3 years ago

Friendly reminder that this solution rocks! Thank you very much and happy new year :) It is fun to know where things get slow in the "pre-loading".

glensc commented 3 years ago

If your bottleneck is in an autoloader, you have some serious problems, duh :)