你們都知道 laravel 項目寫起來是挺爽,可是在生產環境性能不高,咱們來抽絲剝繭分析我本身項目的運行時間消耗:php
步驟 | 耗時 |
---|---|
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\RegisterProviders
和 Illuminate\Foundation\Bootstrap\BootProviders
的 bootstrap
方法時,消耗時間是大頭。laravel
Illuminate\Foundation\Bootstrap\RegisterProviders
是用於註冊服務提供者的。Illuminate\Foundation\Bootstrap\BootProviders
是用於啓動服務提供者的。php artisan serve
自帶了優化機制,上面數據僅體現首次加載的耗時。二次加載時會相比少不少。但此優化在 fpm 下無效。咱們進一步分析。git
\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\Application
ide
/** * 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
佔用 37msDingo\Api\Provider\LaravelServiceProvider
佔用 20msIlluminate\Database\DatabaseServiceProvider
佔用 9msOvertrue\LaravelWeChat\ServiceProvider
佔用 9ms服務提供者 | 啓動時間 | 請求時 |
---|---|---|
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