大家都知道 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. ORM进阶:Hibernate框架搭建及开发

    本节将開始.使用hibernate搭建持久层.当然在决定用不用之前,还请斟酌一下是否使用.了解一下Hibernate的优缺点. Hibernate优劣对照 Hibernate是一个持久的ORM框架.首 ...

  2. SQL SERVER 读书笔记:非聚集索引

    对于有聚集索引的表,数据存储在聚集索引的叶子节点,而非聚集索引则存储 索引键值 和 聚集索引键值.对于非聚集索引,如果查找的字段没有包含在索引键值,则还要根据聚集索引键值来查找详细数据,此谓 Book ...

  3. luogu2054 洗牌 同余方程

    题目大意 对于扑克牌的一次洗牌是这样定义的,将一叠N(N为偶数)张扑克牌平均分成上下两叠,取下面一叠的第一张作为新的一叠的第一张,然后取上面一叠的第一张作为新的一叠的第二张,再取下面一叠的第二张作为新 ...

  4. luogu3366 【模板】 最小生成树 Prim

    题目大意 给出一个无向图,求出最小生成树,如果该图不连通,则输出orz. 概念 对于一个无向图,要求选出一些边,使得图上的每一个节点互相连通,且边权和最小.选出的边与节点形成的子图必然是颗树,这棵树叫 ...

  5. POJ1179 Polygon 区间DP

    题目大意: 多边形游戏,有N个顶点的多边形,3 <= N <= 50 ,多边形有N条边,每个顶点中有一个数字(可正可负),每条边上或者是“+”号,或者是“*”号.边从1到N编号,首先选择一 ...

  6. bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

    1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...

  7. DDos攻击,使用深度学习中 栈式自编码的算法

    转自:http://www.airghc.top/2016/11/10/Dection-DDos/ 最近研究了一篇论文,关于检测DDos攻击,使用了深度学习中 栈式自编码的算法,现在简要介绍一下内容论 ...

  8. 自己实现的一个 .net 缓存类(原创)

    public class CacheContainer { private static Hashtable ht = new Hashtable(); /// <summary> /// ...

  9. [HTML&CSS] 条件注释判断浏览器

    <!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--><!--[if IE]> 所有的IE可识别 <![e ...

  10. ZOJ-3988 2017CCPC-秦皇岛 Prime Set 二分图最大匹配 匈牙利

    题面 题意:给你n个数,你可以选择2个和为质数的数为一对,每个数可以重复选择,你最多选k对,问你最多能选多少个不同数出来 题解:首先思考怎么样的数和为质数,2个偶数相加不行,除了1+1以外2个奇数相加 ...