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

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 方法时,消耗时间是大头。

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

我们进一步分析。


RegisterProviders 耗时

\Illuminate\Foundation\Bootstrap\RegisterProviders::bootstrap 方法代码如下:

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

所以我们还是回到了 \Illuminate\Foundation\Application 这个文件:


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

步骤 耗时
Illuminate\Foundation\ProviderRepository::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);
}

又回到 \Illuminate\Foundation\Application

    /**
* 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

一次 Laravel 性能分析全程笔记的更多相关文章

  1. 老李分享:《Java Performance》笔记1——性能分析基础 1

    老李分享:<Java Performance>笔记1——性能分析基础   1.性能分析两种方法: (1).自顶向下: 应用开发人员通过着眼于软件栈顶层的应用,从上往下寻找性能优化的机会. ...

  2. 「功能笔记」性能分析工具gprof使用笔记

    根据网上信息整理所成. 功能与优劣 gprof实际上只是一个用于读取profile结果文件的工具.gprof采用混合方法来收集程序的统计信息,它使用检测方法,在编译过程中在函数入口处插入计数器用于收集 ...

  3. Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则

    Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...

  4. Java性能调优笔记

    Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多. ...

  5. PHP 性能分析第三篇: 性能调优实战

    注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或  PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 ...

  6. Traceview 性能分析工具

    简介 TraceView 是 Android 平台配备一个很好的性能分析的工具.它可以通过图形化的方式让我们了解我们要跟踪的程序的性能,并且能具体到 method.详细内容参考:http://deve ...

  7. python性能分析(一)——使用timeit给你的程序打个表吧

    前言 我们可以通过查看程序核心算法的代码,得知核心算法的渐进上界或者下界,从而大概估计出程序在运行时的效率,但是这并不够直观,也不一定十分靠谱(在整体程序中仍有一些不可忽略的运行细节在估计时被忽略了) ...

  8. 使用 xhprof 进行 php 的性能分析

    基于本机环境(php7,macos) 1.xhprof 扩展 php7 下安装 xhprof 扩展: git clone https://github.com/longxinH/xhprof cd x ...

  9. MySQL监控、性能分析——工具篇

    https://blog.csdn.net/leamonjxl/article/details/6431444 MySQL越来越被更多企业接受,随着企业发展,MySQL存储数据日益膨胀,MySQL的性 ...

随机推荐

  1. Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

    1.Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理 2. 自定义注解: 使用@interfac ...

  2. HDU 2296

    很明显的DP状态了,设dp[i][j],设当前在状态点i,经过j步能得到的最大分值.也是从root直接扩展就可以了. 至于字符串,实在有点困难,开始想着记录路径,但后来发现路径从后往前回溯不一定是字典 ...

  3. CSTC 选课

    选课 [问题描述] 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分, ...

  4. [Javascript Crocks] Create a Maybe with a `safe` Utility Function

    In this lesson, we’ll create a safe function that gives us a flexible way to create Maybes based on ...

  5. 软件project师周兆熊给IT学子的倾情奉献

    [来信] 贺老师: 你好,我是中兴通讯的一名软件开发project师,名叫周兆熊. 近期看了您的新书<逆袭大学:传给IT学子的正能量>,感觉你真心为当代学子答疑解惑.非常值得敬佩! 从上大 ...

  6. @RequiresPermissions 注解说明

    @RequiresAuthentication验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时.@RequiresUser验证用户是否被记忆,user有 ...

  7. Android Handler消息机制深入浅出

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38408493 作为Android开发者,Handler这个类应该是再熟悉只是了.由于差点儿不 ...

  8. string字符串常量池在内存中的位置

    这里仅仅是举个简单的样例说明字符串常量池在内存中的位置. 闲言少叙,直接上代码. <span style="font-size: large;">import java ...

  9. Mina airQQ聊天开门见山篇(一)

    Mina airQQ聊天开门见山篇(一) 近期项目可能要用到Mina,这个礼拜就在看这个框架,所以想写个小小的聊天的demo来巩固下,打算用几篇博客来记录下相关的知识 client用的是Flex Ai ...

  10. 分享3个Putty配色方案【转】

    本文转载自:https://www.coder4.com/archives/1506 分享3个Putty配色方案 4 Replies 虽然服务器都是Linux的,平时也基本用Linux,但是难免还是要 ...