一次 Laravel 性能分析全程笔记
大家都知道 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\RegisterProviders 和 Illuminate\Foundation\Bootstrap\BootProviders 的 bootstrap 方法时,消耗时间是大头。
- 类
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占用 37msDingo\Api\Provider\LaravelServiceProvider占用 20msIlluminate\Database\DatabaseServiceProvider占用 9msOvertrue\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 性能分析全程笔记的更多相关文章
- 老李分享:《Java Performance》笔记1——性能分析基础 1
老李分享:<Java Performance>笔记1——性能分析基础 1.性能分析两种方法: (1).自顶向下: 应用开发人员通过着眼于软件栈顶层的应用,从上往下寻找性能优化的机会. ...
- 「功能笔记」性能分析工具gprof使用笔记
根据网上信息整理所成. 功能与优劣 gprof实际上只是一个用于读取profile结果文件的工具.gprof采用混合方法来收集程序的统计信息,它使用检测方法,在编译过程中在函数入口处插入计数器用于收集 ...
- Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则
Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...
- Java性能调优笔记
Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多. ...
- PHP 性能分析第三篇: 性能调优实战
注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或 PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 ...
- Traceview 性能分析工具
简介 TraceView 是 Android 平台配备一个很好的性能分析的工具.它可以通过图形化的方式让我们了解我们要跟踪的程序的性能,并且能具体到 method.详细内容参考:http://deve ...
- python性能分析(一)——使用timeit给你的程序打个表吧
前言 我们可以通过查看程序核心算法的代码,得知核心算法的渐进上界或者下界,从而大概估计出程序在运行时的效率,但是这并不够直观,也不一定十分靠谱(在整体程序中仍有一些不可忽略的运行细节在估计时被忽略了) ...
- 使用 xhprof 进行 php 的性能分析
基于本机环境(php7,macos) 1.xhprof 扩展 php7 下安装 xhprof 扩展: git clone https://github.com/longxinH/xhprof cd x ...
- MySQL监控、性能分析——工具篇
https://blog.csdn.net/leamonjxl/article/details/6431444 MySQL越来越被更多企业接受,随着企业发展,MySQL存储数据日益膨胀,MySQL的性 ...
随机推荐
- ORM进阶:Hibernate框架搭建及开发
本节将開始.使用hibernate搭建持久层.当然在决定用不用之前,还请斟酌一下是否使用.了解一下Hibernate的优缺点. Hibernate优劣对照 Hibernate是一个持久的ORM框架.首 ...
- SQL SERVER 读书笔记:非聚集索引
对于有聚集索引的表,数据存储在聚集索引的叶子节点,而非聚集索引则存储 索引键值 和 聚集索引键值.对于非聚集索引,如果查找的字段没有包含在索引键值,则还要根据聚集索引键值来查找详细数据,此谓 Book ...
- luogu2054 洗牌 同余方程
题目大意 对于扑克牌的一次洗牌是这样定义的,将一叠N(N为偶数)张扑克牌平均分成上下两叠,取下面一叠的第一张作为新的一叠的第一张,然后取上面一叠的第一张作为新的一叠的第二张,再取下面一叠的第二张作为新 ...
- luogu3366 【模板】 最小生成树 Prim
题目大意 给出一个无向图,求出最小生成树,如果该图不连通,则输出orz. 概念 对于一个无向图,要求选出一些边,使得图上的每一个节点互相连通,且边权和最小.选出的边与节点形成的子图必然是颗树,这棵树叫 ...
- POJ1179 Polygon 区间DP
题目大意: 多边形游戏,有N个顶点的多边形,3 <= N <= 50 ,多边形有N条边,每个顶点中有一个数字(可正可负),每条边上或者是“+”号,或者是“*”号.边从1到N编号,首先选择一 ...
- bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)
1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...
- DDos攻击,使用深度学习中 栈式自编码的算法
转自:http://www.airghc.top/2016/11/10/Dection-DDos/ 最近研究了一篇论文,关于检测DDos攻击,使用了深度学习中 栈式自编码的算法,现在简要介绍一下内容论 ...
- 自己实现的一个 .net 缓存类(原创)
public class CacheContainer { private static Hashtable ht = new Hashtable(); /// <summary> /// ...
- [HTML&CSS] 条件注释判断浏览器
<!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--><!--[if IE]> 所有的IE可识别 <![e ...
- ZOJ-3988 2017CCPC-秦皇岛 Prime Set 二分图最大匹配 匈牙利
题面 题意:给你n个数,你可以选择2个和为质数的数为一对,每个数可以重复选择,你最多选k对,问你最多能选多少个不同数出来 题解:首先思考怎么样的数和为质数,2个偶数相加不行,除了1+1以外2个奇数相加 ...