大家都知道 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. 解决Chrome在隐身模式下无法播放Flash视频

    在地址栏输入: chrome://flags/#prefer-html-over-flash 打开如下界面,并设置成如下所示: 然后点击左下方重启按钮: 参考: http://www.cnblogs. ...

  2. 汉澳sinox2014x64server已经能够下载

    大家快去下载,用迅雷快速下载 下载地址 ftp://sinox.3322.org/sinox2014x64server.img 已经能够下载 ftp://sinox.3322.org/sinox201 ...

  3. XTU OJ 1207 Welcome to XTCPC (字符串签到题)

    Problem Description Welcome to XTCPC! XTCPC start today, you are going to choose a slogan to celebra ...

  4. runtime objc_msgSend

    runtime objc_msgSend 字数1781 阅读245 评论2 喜欢7  前言 想要通过runtime发送消息,就必须要掌握runtime如何发送消息,是调用哪个函数?又是如何调用的?本篇 ...

  5. 关于View的ScrollTo, getScrollX 和 getScrollY

    下载地址:源代码 当利用 Scroller 去滑动屏幕或者扩展 ScrollView 的时候,总是会用到 getScrollX 和 getScrollY 去获取当前View 滑动到的位置,那么getS ...

  6. PHP获取数组长度的方法 函数参数的比较

    在php中获取数组长度方法很简单,php为我们提供了两个函数可以计算一维数组长度,如count,sizeof都可以直接统计数组长度哦,下面我们来看几个实例吧.php如何获取数组的长度,使用php函数c ...

  7. Swift-理解值类型

    在这里,我们要讲讲值类型和写时复制.在 swift 的标准库中,所有的集合类型都使用了写时复制.我们在本篇文章中看一下写时复制如何工作的,并且如何实现它. 引用类型 使用 swift 的 Data 和 ...

  8. 委托delegate,Action,Func,Predicate

    C#委托的介绍(delegate.Action.Func.predicate) 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 ...

  9. [POJ 2282] The Counting Problem

    [题目链接] http://poj.org/problem?id=2282 [算法] 数位DP [代码] #include <algorithm> #include <bitset& ...

  10. javaWeb中URLEncoder.encode编码需要调用两次

    今天碰到一个问题,在Controller类中一个方法跳转到该类中的另一个方法,带着中文参数,在跳转之前对该参数进行编码: msg = java.net.URLEncoder.encode(msg,&q ...