一次 Laravel 性能分析全程筆記

你們都知道 laravel 項目寫起來是挺爽,可是在生產環境性能不高,咱們來抽絲剝繭分析我本身項目的運行時間消耗:php

Bootstrap 耗時

步驟 耗時
Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables 0.3058910369873
Illuminate\Foundation\Bootstrap\LoadConfiguration 3.6571025848389
Illuminate\Foundation\Bootstrap\HandleExceptions 0.78296661376953
Illuminate\Foundation\Bootstrap\RegisterFacades 9.0579986572266
Illuminate\Foundation\Bootstrap\RegisterProviders 101.02701187134
Illuminate\Foundation\Bootstrap\BootProviders 96.982002258301

觀察初步結論: laravel 在調用 Illuminate\Foundation\Bootstrap\RegisterProvidersIlluminate\Foundation\Bootstrap\BootProvidersbootstrap 方法時,消耗時間是大頭。laravel

  • Illuminate\Foundation\Bootstrap\RegisterProviders 是用於註冊服務提供者的。
  • Illuminate\Foundation\Bootstrap\BootProviders 是用於啓動服務提供者的。
  • laravel 的內置server php artisan serve 自帶了優化機制,上面數據僅體現首次加載的耗時。二次加載時會相比少不少。但此優化在 fpm 下無效。

咱們進一步分析。git


RegisterProviders 耗時

\Illuminate\Foundation\Bootstrap\RegisterProviders::bootstrap 方法代碼以下:github

/**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $app->registerConfiguredProviders();
    }

因此咱們仍是回到了 \Illuminate\Foundation\Application 這個文件:web

/**
     * Register all of the configured providers.
     *
     * @return void
     */
    public function registerConfiguredProviders()
    {
        $providers = Collection::make($this->config['app.providers'])
                        ->partition(function ($provider) {
                            return Str::startsWith($provider, 'Illuminate\\');
                        });

        $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);

        (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                    ->load($providers->collapse()->toArray());
    }

針對上面的 (new ProviderRepository)->load 進行耗時分析發現數據爲bootstrap

步驟 耗時
Illuminate\Foundation\ProviderRepository::load 61.771869659424

毋庸置疑這就是消耗時間的大頭。 segmentfault

裏面的代碼爲app

/**
     * Register the application service providers.
     *
     * @param  array  $providers
     * @return void
     */
    public function load(array $providers)
    {
        $manifest = $this->loadManifest();

        // First we will load the service manifest, which contains information on all
        // service providers registered with the application and which services it
        // provides. This is used to know which services are "deferred" loaders.
        if ($this->shouldRecompile($manifest, $providers)) {
            $manifest = $this->compileManifest($providers);
        }

        // Next, we will register events to load the providers for each of the events
        // that it has requested. This allows the service provider to defer itself
        // while still getting automatically loaded when a certain event occurs.
        foreach ($manifest['when'] as $provider => $events) {
            $this->registerLoadEvents($provider, $events);
        }

        // We will go ahead and register all of the eagerly loaded providers with the
        // application so their services can be registered with the application as
        // a provided service. Then we will set the deferred service list on it.
        foreach ($manifest['eager'] as $provider) {
            $this->app->register($provider);
        }

        $this->app->addDeferredServices($manifest['deferred']);
    }

而再通過定位,發現慢在這一行composer

foreach ($manifest['eager'] as $provider) {
            $this->app->register($provider);
        }

又回到 \Illuminate\Foundation\Applicationide

/**
     * Register a service provider with the application.
     *
     * @param  \Illuminate\Support\ServiceProvider|string  $provider
     * @param  array  $options
     * @param  bool   $force
     * @return \Illuminate\Support\ServiceProvider
     */
    public function register($provider, $options = [], $force = false)
    {
        if (($registered = $this->getProvider($provider)) && ! $force) {
            return $registered;
        }

        // If the given "provider" is a string, we will resolve it, passing in the
        // application instance automatically for the developer. This is simply
        // a more convenient way of specifying your service provider classes.
        if (is_string($provider)) {
            $provider = $this->resolveProvider($provider);
        }

        if (method_exists($provider, 'register')) {
            $provider->register();
        }

        // If there are bindings / singletons set as properties on the provider we
        // will spin through them and register them with the application, which
        // serves as a convenience layer while registering a lot of bindings.
        if (property_exists($provider, 'bindings')) {
            foreach ($provider->bindings as $key => $value) {
                $this->bind($key, $value);
            }
        }

        if (property_exists($provider, 'singletons')) {
            foreach ($provider->singletons as $key => $value) {
                $this->singleton($key, $value);
            }
        }

        $this->markAsRegistered($provider);

        // If the application has already booted, we will call this boot method on
        // the provider class so it has an opportunity to do its boot logic and
        // will be ready for any usage by this developer's application logic.
        if ($this->booted) {
            $this->bootProvider($provider);
        }

        return $provider;
    }

在 register 方法中,根據 get_class($provider) 和 執行耗時,得出如下數據

步驟 耗時
Illuminate\Events\EventServiceProvider 0.02197265625
Illuminate\Log\LogServiceProvider 0.005859375
Illuminate\Routing\RoutingServiceProvider 0.011962890625
Illuminate\Auth\AuthServiceProvider 0.024169921875
Illuminate\Cookie\CookieServiceProvider 0.0048828125
Illuminate\Database\DatabaseServiceProvider 9.678955078125
Illuminate\Encryption\EncryptionServiceProvider 0.00732421875
Illuminate\Filesystem\FilesystemServiceProvider 0.014892578125
Illuminate\Foundation\Providers\FormRequestServiceProvider 0.0009765625
Illuminate\Foundation\Providers\FoundationServiceProvider 0.416015625
Illuminate\Notifications\NotificationServiceProvider 0.011962890625
Illuminate\Pagination\PaginationServiceProvider 5.04296875
Illuminate\Session\SessionServiceProvider 0.072021484375
Illuminate\View\ViewServiceProvider 0.01318359375
Cog\Laravel\Love\Providers\LoveServiceProvider 0.01708984375
Dingo\Api\Provider\RoutingServiceProvider 0.0146484375
Dingo\Api\Provider\HttpServiceProvider 0.03271484375
Dingo\Api\Provider\LaravelServiceProvider 20.23583984375
Fideloper\Proxy\TrustedProxyServiceProvider 0.001953125
InfyOm\AdminLTETemplates\AdminLTETemplatesServiceProvider 0.001953125
InfyOm\Generator\InfyOmGeneratorServiceProvider 0.045166015625
JeroenNoten\LaravelAdminLte\ServiceProvider 0.013671875
Laracasts\Flash\FlashServiceProvider 0.013916015625
Laravelfy\Validator\ServiceProvider 0.001953125
Lshorz\Luocaptcha\LCaptchaServiceProvider 0.01171875
Maatwebsite\Excel\ExcelServiceProvider 6.778076171875
Overtrue\LaravelWeChat\ServiceProvider 9.040771484375
Prettus\Repository\Providers\EventServiceProvider 0.00390625
Prettus\Repository\Providers\RepositoryServiceProvider 1.244140625
Spatie\Permission\PermissionServiceProvider 0.3759765625
Tymon\JWTAuth\Providers\LaravelServiceProvider 0.03515625
Collective\Html\HtmlServiceProvider 0.025146484375
Yajra\DataTables\HtmlServiceProvider 2.22314453125
Yajra\DataTables\ButtonsServiceProvider 4.593017578125
Yajra\DataTables\DataTablesServiceProvider 0.333984375
App\Providers\AppServiceProvider 0.001953125
App\Providers\AuthServiceProvider 0.001953125
App\Providers\EventServiceProvider 0.001953125
App\Providers\RouteServiceProvider 0.001708984375
App\Providers\ResponseMacroServicePrivoder 37.69677734375
Overtrue\LaravelLang\TranslationServiceProvider 0.01220703125
Illuminate\Validation\ValidationServiceProvider 0.029052734375
Illuminate\Cache\CacheServiceProvider 0.01318359375
Illuminate\Hashing\HashServiceProvider 0.031005859375

得出 RegisterProviders 瓶頸的結論

  • App\Providers\ResponseMacroServicePrivoder 佔用 37ms
  • Dingo\Api\Provider\LaravelServiceProvider 佔用 20ms
  • Illuminate\Database\DatabaseServiceProvider 佔用 9ms
  • Overtrue\LaravelWeChat\ServiceProvider 佔用 9ms

BootProviders 耗時

服務提供者 啓動時間 請求時
Illuminate\Database\DatabaseServiceProvider::boot 0.851074875 3.6809083125
Illuminate\Foundation\Providers\FormRequestServiceProvider::boot 0.022949875 0.0290524375
Illuminate\Notifications\NotificationServiceProvider::boot 2.113769125 9.91894525
Illuminate\Pagination\PaginationServiceProvider::boot 0.062988125 0.089843
EasyWeChatComposer\Laravel\ServiceProvider::boot 6.5910643125 22.644042875
Cog\Laravel\Love\Providers\LoveServiceProvider::boot 0.6311035625 2.3010250625
Dingo\Api\Provider\LaravelServiceProvider::boot 9.228027375 53.9980465
Fideloper\Proxy\TrustedProxyServiceProvider::boot 0.1589356875 0.6091309375
InfyOm\AdminLTETemplates\AdminLTETemplatesServiceProvider::boot 0.033691625 0.0410155
Prettus\Repository\Providers\EventServiceProvider::boot 0.020996375 0.0432120625
Prettus\Repository\Providers\RepositoryServiceProvider::boot 1.7600095625 8.361816625
Laracasts\Flash\FlashServiceProvider::boot 0.191894125 0.066894125
InfyOm\Generator\InfyOmGeneratorServiceProvider::boot 0.0832513125 0.019042875
JeroenNoten\LaravelAdminLte\ServiceProvider::boot 3.2441405 17.807128625
Laravelfy\Validator\ServiceProvider::boot 2.940917875 10.8391118125
Lshorz\Luocaptcha\LCaptchaServiceProvider::boot 0.0832513125 0.075683375
Overtrue\LaravelWeChat\ServiceProvider::boot 0.074707125 0.0139165625
Spatie\Permission\PermissionServiceProvider::boot 9.5026856875 15.3239749375
Tymon\JWTAuth\Providers\LaravelServiceProvider::boot 1.070800125 11.508300125
Yajra\DataTables\DataTablesServiceProvider::boot 0.2839356875 1.0837404375
Yajra\DataTables\HtmlServiceProvider::boot 0.0827631875 0.0651856875
Maatwebsite\Excel\ExcelServiceProvider::boot 0.0461428125 0.0097655
Yajra\DataTables\ButtonsServiceProvider::boot 0.0529785625 0.046875
App\Providers\AppServiceProvider::boot 0.1179191875 0.0979000625
App\Providers\AuthServiceProvider::boot 0.1901856875 0.437988125
App\Providers\EventServiceProvider::boot 0.196777375 0.8210441875
App\Providers\RouteServiceProvider::boot 4.6032714375 12.817871375
App\Providers\ResponseMacroServicePrivoder::boot 5.6691893125 16.917968
Laravel\Tinker\TinkerServiceProvider::boot 0.3859868125 null
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::boot 0.1750488125 null

緣由分析

  • EasyWeChatComposer\Laravel\ServiceProvider::boot 的啓動速度,略慢,分析緣由: 代碼 Github boot 方法中,加載了路由。而 Laravel 的路由,確實是比較慢的。

[未完]

原文地址:https://segmentfault.com/a/1190000016411386

相關文章
相關標籤/搜索