zoukankan      html  css  js  c++  java
  • 一次 Laravel 性能分析全程笔记

    大家都知道 laravel 项目写起来是挺爽,但是在生产环境性能不高,我们来抽丝剥茧分析我自己项目的运行时间消耗:

    Bootstrap 耗时

    步骤 耗时
    IlluminateFoundationBootstrapLoadEnvironmentVariables 0.3058910369873
    IlluminateFoundationBootstrapLoadConfiguration 3.6571025848389
    IlluminateFoundationBootstrapHandleExceptions 0.78296661376953
    IlluminateFoundationBootstrapRegisterFacades 9.0579986572266
    IlluminateFoundationBootstrapRegisterProviders 101.02701187134
    IlluminateFoundationBootstrapBootProviders 96.982002258301

    观察初步结论: laravel 在调用 IlluminateFoundationBootstrapRegisterProvidersIlluminateFoundationBootstrapBootProvidersbootstrap 方法时,消耗时间是大头。

    • IlluminateFoundationBootstrapRegisterProviders 是用于注册服务提供者的。
    • IlluminateFoundationBootstrapBootProviders 是用于启动服务提供者的。
    • laravel 的内置server php artisan serve 自带了优化机制,上面数据仅体现首次加载的耗时。二次加载时会相比少很多。但此优化在 fpm 下无效。

    我们进一步分析。


    RegisterProviders 耗时

    IlluminateFoundationBootstrapRegisterProviders::bootstrap 方法代码如下:

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

    所以我们还是回到了 IlluminateFoundationApplication 这个文件:

    
        /**
         * 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 进行耗时分析发现数据为

    步骤 耗时
    IlluminateFoundationProviderRepository::load 61.771869659424

    毋庸置疑这就是消耗时间的大头。

    里面的代码为

    
        /**
         * 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']);
        }
    

    而再经过定位,发现慢在这一行

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

    又回到 IlluminateFoundationApplication

        /**
         * Register a service provider with the application.
         *
         * @param  IlluminateSupportServiceProvider|string  $provider
         * @param  array  $options
         * @param  bool   $force
         * @return IlluminateSupportServiceProvider
         */
        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) 和 执行耗时,得出以下数据

    步骤 耗时
    IlluminateEventsEventServiceProvider 0.02197265625
    IlluminateLogLogServiceProvider 0.005859375
    IlluminateRoutingRoutingServiceProvider 0.011962890625
    IlluminateAuthAuthServiceProvider 0.024169921875
    IlluminateCookieCookieServiceProvider 0.0048828125
    IlluminateDatabaseDatabaseServiceProvider 9.678955078125
    IlluminateEncryptionEncryptionServiceProvider 0.00732421875
    IlluminateFilesystemFilesystemServiceProvider 0.014892578125
    IlluminateFoundationProvidersFormRequestServiceProvider 0.0009765625
    IlluminateFoundationProvidersFoundationServiceProvider 0.416015625
    IlluminateNotificationsNotificationServiceProvider 0.011962890625
    IlluminatePaginationPaginationServiceProvider 5.04296875
    IlluminateSessionSessionServiceProvider 0.072021484375
    IlluminateViewViewServiceProvider 0.01318359375
    CogLaravelLoveProvidersLoveServiceProvider 0.01708984375
    DingoApiProviderRoutingServiceProvider 0.0146484375
    DingoApiProviderHttpServiceProvider 0.03271484375
    DingoApiProviderLaravelServiceProvider 20.23583984375
    FideloperProxyTrustedProxyServiceProvider 0.001953125
    InfyOmAdminLTETemplatesAdminLTETemplatesServiceProvider 0.001953125
    InfyOmGeneratorInfyOmGeneratorServiceProvider 0.045166015625
    JeroenNotenLaravelAdminLteServiceProvider 0.013671875
    LaracastsFlashFlashServiceProvider 0.013916015625
    LaravelfyValidatorServiceProvider 0.001953125
    LshorzLuocaptchaLCaptchaServiceProvider 0.01171875
    MaatwebsiteExcelExcelServiceProvider 6.778076171875
    OvertrueLaravelWeChatServiceProvider 9.040771484375
    PrettusRepositoryProvidersEventServiceProvider 0.00390625
    PrettusRepositoryProvidersRepositoryServiceProvider 1.244140625
    SpatiePermissionPermissionServiceProvider 0.3759765625
    TymonJWTAuthProvidersLaravelServiceProvider 0.03515625
    CollectiveHtmlHtmlServiceProvider 0.025146484375
    YajraDataTablesHtmlServiceProvider 2.22314453125
    YajraDataTablesButtonsServiceProvider 4.593017578125
    YajraDataTablesDataTablesServiceProvider 0.333984375
    AppProvidersAppServiceProvider 0.001953125
    AppProvidersAuthServiceProvider 0.001953125
    AppProvidersEventServiceProvider 0.001953125
    AppProvidersRouteServiceProvider 0.001708984375
    AppProvidersResponseMacroServicePrivoder 37.69677734375
    OvertrueLaravelLangTranslationServiceProvider 0.01220703125
    IlluminateValidationValidationServiceProvider 0.029052734375
    IlluminateCacheCacheServiceProvider 0.01318359375
    IlluminateHashingHashServiceProvider 0.031005859375

    得出 RegisterProviders 瓶颈的结论

    • AppProvidersResponseMacroServicePrivoder 占用 37ms
    • DingoApiProviderLaravelServiceProvider 占用 20ms
    • IlluminateDatabaseDatabaseServiceProvider 占用 9ms
    • OvertrueLaravelWeChatServiceProvider 占用 9ms

    BootProviders 耗时

    服务提供者 启动时间 请求时
    IlluminateDatabaseDatabaseServiceProvider::boot 0.851074875 3.6809083125
    IlluminateFoundationProvidersFormRequestServiceProvider::boot 0.022949875 0.0290524375
    IlluminateNotificationsNotificationServiceProvider::boot 2.113769125 9.91894525
    IlluminatePaginationPaginationServiceProvider::boot 0.062988125 0.089843
    EasyWeChatComposerLaravelServiceProvider::boot 6.5910643125 22.644042875
    CogLaravelLoveProvidersLoveServiceProvider::boot 0.6311035625 2.3010250625
    DingoApiProviderLaravelServiceProvider::boot 9.228027375 53.9980465
    FideloperProxyTrustedProxyServiceProvider::boot 0.1589356875 0.6091309375
    InfyOmAdminLTETemplatesAdminLTETemplatesServiceProvider::boot 0.033691625 0.0410155
    PrettusRepositoryProvidersEventServiceProvider::boot 0.020996375 0.0432120625
    PrettusRepositoryProvidersRepositoryServiceProvider::boot 1.7600095625 8.361816625
    LaracastsFlashFlashServiceProvider::boot 0.191894125 0.066894125
    InfyOmGeneratorInfyOmGeneratorServiceProvider::boot 0.0832513125 0.019042875
    JeroenNotenLaravelAdminLteServiceProvider::boot 3.2441405 17.807128625
    LaravelfyValidatorServiceProvider::boot 2.940917875 10.8391118125
    LshorzLuocaptchaLCaptchaServiceProvider::boot 0.0832513125 0.075683375
    OvertrueLaravelWeChatServiceProvider::boot 0.074707125 0.0139165625
    SpatiePermissionPermissionServiceProvider::boot 9.5026856875 15.3239749375
    TymonJWTAuthProvidersLaravelServiceProvider::boot 1.070800125 11.508300125
    YajraDataTablesDataTablesServiceProvider::boot 0.2839356875 1.0837404375
    YajraDataTablesHtmlServiceProvider::boot 0.0827631875 0.0651856875
    MaatwebsiteExcelExcelServiceProvider::boot 0.0461428125 0.0097655
    YajraDataTablesButtonsServiceProvider::boot 0.0529785625 0.046875
    AppProvidersAppServiceProvider::boot 0.1179191875 0.0979000625
    AppProvidersAuthServiceProvider::boot 0.1901856875 0.437988125
    AppProvidersEventServiceProvider::boot 0.196777375 0.8210441875
    AppProvidersRouteServiceProvider::boot 4.6032714375 12.817871375
    AppProvidersResponseMacroServicePrivoder::boot 5.6691893125 16.917968
    LaravelTinkerTinkerServiceProvider::boot 0.3859868125 null
    BarryvdhLaravelIdeHelperIdeHelperServiceProvider::boot 0.1750488125 null

    原因分析

    • EasyWeChatComposerLaravelServiceProvider::boot 的启动速度,略慢,分析原因: 代码 Github boot 方法中,加载了路由。而 Laravel 的路由,确实是比较慢的。

    [未完]

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

  • 相关阅读:
    视频安防智能监控系统管理平台EasyNVS切换导航报错Cannot find module ‘@/views/sys/user’问题
    视频安防智能监控系统管理平台EasyNVS手机端扫码直播展示无信号但是PC端可以播放是什么原因?
    RTSP协议视频智能安防监控平台EasyNVR接入大华摄像头无法拉取H265格式视频流如何解决?
    RTSP协议视频智能安防监控平台EasyNVR录像播放及下载接口如何返回在线m3u8格式视频流?
    网页无插件直播视频平台EasyNVR老版本更新版本后CPU占用过高怎么解决?
    【解决方案】如何通过EasyNVR+EasyNVS搭建一套高清智能化的高速公路视频监控管理系统?
    【解决方案】现代化工厂如何实现智能化视频管理?EasyNVR安防视频监控系统打造智慧工厂
    【解决方案】EasyNVR视频边缘计算网关如何实现智慧消防?
    RTSP协议智能安防监控系统EasyNVR硬件设备IP探测软件EasySearcher无法运行如何修复?
    就地过年带旺“云游”,RTSP协议视频监控智能分析平台EasyNVR助力景区“慢直播”
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9971337.html
Copyright © 2011-2022 走看看