我们在日常的开发过程中,经常会发现我们开发的一些应用有些时候加载会很慢,那么就涉及到怎么去优化的问题了。今天我就根据我的经验来跟大家分析一下。
在我平时做项目的过程中,会用到以下方式进行性能优化,这里以laravel框架为例:
一、自带命令
终端通过 php artisan
查看全部命令
1、路由缓存优化:
在web.php
中,我们使用的路由基本上都是group
、middleware
或者资源路由等这些复杂的格式,然后项目访问后,都需要解析这些复杂的格式,然后生成具体的路由对象RouteCollection
。我们就在想,有没有一种机制把这些路由对象使用PHP文件先给它生成,这就要用到路由缓存。laravel为我们提供了这种机制。执行命令:php artisan route:cache
,如果路由中有闭包函数的用法,请先处理修改。执行完命令后,会在项目的bootstrap/cache中生成一个route.php
文件,这个就是路由缓存优化。
2、配置缓存优化
项目中,我们的配置文件其实也是很复杂的,它需要读取config下面的.php配置文件,还需要读取.env里面的配置文件,这些配置文件都是比较耗资源的,那么我们就需要一个方法把这些配置文件都提取出来。执行命令:php artisan config:cache
,然后也会在项目的bootstrap/cache中生成一个config.php
文件,这个就是路由缓存优化。
3、类加载优化
我们的很多类是基于psr4来进行加载的,虽然这个psr4的规则是很好用的,但实际上我们把这些类名和类文件使用数组进行映射,加载类的时候直接去数组中进行寻找,这也是一种优化方法。意思就是说psr4定义的是我们的文件夹名字和我们的命名空间的映射一一对应。使用psr4我们就需要去根据命名空间我们使用每个类的命名空间的时候去每个文件夹下面去寻找,这种方式有种递归的意思,但这个肯能是有点慢,如果我们有一个大列表把我们这个项目中所有的类和这个类所在的文件都进行映射,那我们获取数据的时候直接去这里面把我们的类或文件提取出来。laravel也为我们提供了这种方法,执行命令:php artisan optimize
,然后生成的文件在vendor/composer里面的autoload_classmap.php
文件中。这样就不需要一层层的解析了。
二、debugbar
借助于第三方工具进行调试查看,网站哪些地方甚至每个页面执行了哪些sql查询,执行时间等详细的操作,我们都可以看的到,然后根据实际情况进行优化。
1、安装debugbar
,地址:https://github.com/barryvdh/laravel-debugbar
。执行命令:
composer require barryvdh/laravel-debugbar
2、获取配置文件。注:laravel5.6以上版本不需要注册服务提供者
php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"
3、测试:
浏览器访问项目,底部会出现debugbar
的调试器。访问一个页面,这里以分类管理为例,如图:
解析:这里分类管理的首页,执行了这么多查询,很显然有些sql出现重复查询,这样导致页面加载速度很慢。那么接下来怎么去优化它。找到对应控制器,原代码如图
这里的重复查询经过我的优化后的结果如下图:
这样的代码是不是更加简洁。。并且性能也得到了优化,如图:
三、预加载
如果有人在用laravel开发项目,感觉laravel慢的话,大部分都是由于数据库查询过多,就是没有合理的使用预加载,像我们上面第一个图,查询parent_id
的次数比较多,这种情况就是没有使用预加载的过程。那么预加载到底是什么意思呢?
定义:预加载就是数据在传递给模板的时候,它已经完全的渲染出来了,就MVC三层模型在view层是只做数据的渲染,如果你在view层做了数据库的查询,那就很容易出现非常慢的情况。所以我建议在控制器中尽量把能传递给view的数据都渲染出来。预加载有两种方式:with
和 load
。
使用:尽量不用foreach,使用关联模型,模型定义好关联关系后,控制器中直接调用模型里面的方法。
四、慢sql查找
慢sql查找意思就是说怎样在项目中快速的找到有哪些sql语句执行很慢,实际上laravel是可以对每个sql进行监听,监听完之后,我们就知道哪些sql执行慢了,针对这些慢查询,我们就可以去数据中建索引或者优化我这个查询。
我这里使用的是DB::listen
,打开app\providers\AppServiceProvider.php
,在boot
方法中加入如下代码:
public function boot()
{
\DB::listen(function ($query) {
$sql = $query->sql;
$bindings = $query->bindings;
$time = $query->time;
//查出sql执行时间大于20ms的语句,若想查看所有语句请把if判断去掉
if($time > 20){
\Log::debug(var_export(compact('sql', 'bindings', 'time'), true));
}
});
}
然后刷新页面,终端通过命令cd/storage/logs
, vim laravel.log
你会看到如下图sql查询时间,这样就很清楚的知道哪些sql查询的慢了。
有的朋友可能会问,我们上面安装了debugbar
,在浏览器下面的调试器中也能看到这些信息,为什么还要在logs
里面去查看?因为当你是接口开发时,这个调试器就看不到这些数据了,所以只能通过logs
文件才能看到。