记一次对 Laravel-permission 项目的性能优化
我最近研究分析了在 SWIS上面创建的项目的性能。令人惊讶的是,最耗费性能的方法之一是优秀的 spatie/laravel-permission
包造成的。
经过查阅更多资料和研究,发现一个可能明显改善的性能问题 。既然解决方案已明确阐述,就很容易编写代码改善,提交请求。
现在这个解决方案已被合并和发布,下面是这个性能问题的分析和如何在自己的项目避免这类问题。
TL;DR: 跳转到结论部分.
性能瓶颈
如果我们抽象的看 spatie/laravel-permission
它主要做两件事:
- 保持一个属于某个模型的权限清单。
- 检查某个模型是否具有权限。
第一点说是性能瓶颈有点牵强。这里的权限数据存放在数据库中,需要的时候将会被读取出来。这个过程是有点慢但也只是执行一次。结果会被缓存下来,后续的请求可以直接使用。
第二点在性能瓶颈的观点上来看确实是一个瓶颈。 这个瓶颈取决于权限的性质和项目的大小, 因为权限会被频繁的检查。 在这个检查的过程中任何的迟钝都会成为整个项目的性能瓶颈。
过滤集合类
过滤权限集合的方法被认为是造成低性能的原因。 它做了如下事情:
$permission = $permissions
->where('id', $id)
->where('guard_name', $guardName)
->first();
修改后:
$permission = $permissions
->filter(function ($permission) use ($id, $guardName) {
return $permission->id === $id && $permission->guard_name === $guardName;
})
->first();
这两个代码段实现了同一件事情,但第二个更快。
性能测试
我正在开发的应用中大约有 150 个不同的权限。 在一个普通的请求中, 大约有 50 个权限需要用 hasPermissionTo
这个方法去检查,当然,有些页面可能需要检查大约 200 个权限。
以下是用来做性能测试的一些设置。
$users = factory(User::class, 150)->make();
$searchForTheseUsers = $users->shuffle()->take(50);
# 方法 1: where
foreach($searchForTheseUsers as $user) {
$result = $users->where('id', '=', $user->id)->first();
}
# 方法 2: 过滤,传递一个模型作为回调
foreach($searchForTheseUsers as $searchUser) {
$result = $users->filter(function($user) use ($searchUser) {
return $user->id === $searchUser->id;
})->first();
}
# 方法 3: 过滤,传递属性作为回调
foreach($searchForTheseUsers as $user) {
$searchId = $user->id;
$result = $users->filter(function($user) use ($searchId) {
return $user->id === $searchId;
})->first();
}
以上三个方法都会被用来测试过滤 1 个属性,2 个属性,3 个属性,所以,用方法 1 过滤三个属性就会是这样:
foreach($searchForTheseUsers as $user) {
$result = $users
->where('id', '=', $user->id)
->where('firstname', '=', $user->firstname)
->where('lastname', '=', $user->lastname)->first();
}
结果
方法 #1 | 方法 #2 | 方法 #3 | |
---|---|---|---|
1个属性 | 0.190 | 0.139 (-27%) | 0.072 (-62%) |
2个属性 | 0.499 | 0.372 (-25%) | 0.196 (-61%) |
3个属性 | 0.488 | 0.603 (+25%) | 0.198 (-59%) |
结论
我们可以得出结论:对一个项目而言,重复的过滤一个大集合会引发严重性能瓶颈。
多属性的过滤明显增加计算成本。
使用 Collection::filter()
代替 Collection::where()
可以提高60%的性能。
警告:传递完整的模型给过滤器回调是很耗费性能的,最好是传递单独的属性。
致谢
感谢 Spatie 和 spatie/laravel-permissions
的贡献者创建如此优秀的包,我非常喜欢使用!感谢 Andru Beldie 指出这些性能问题,我才有机会对其进行调查和纠正。
链接
- spatie/laravel-permission package.
- Issue #550 addressing performance problem.
- Pull request #710 that fixes problems.
更多现代化 PHP 知识,请前往 Laravel / PHP 知识社区
记一次对 Laravel-permission 项目的性能优化的更多相关文章
- Web项目开发性能优化解决方案
web开发性能优化---安全篇 1.ip验证 2.操作日志.安全日志.登录日志 3.SQL注入校验 4.权限管理 5.验证规范(前端.后端.数据库约束) 2014-10-29 08:04 2773 ...
- vuejs项目性能优化总结
在使用elementUI构建公司管理系统时,发现首屏加载时间长,加载的网络资源比较多,对系统的体验性会差一点,而且用webpack打包的vuejs的vendor包会比较大.所以通过搜集网上所有对于vu ...
- vue-cli3项目搭建配置以及性能优化
项目初始化 注意:安装前请确保有安装node.js,并且node>=8.9 全局安装vue npm install -g @vue/cli 如果之前安装了vue旧版本,查看vue --versi ...
- vue项目性能优化总结
在使用elementUI构建公司管理系统时,发现首屏加载时间长,加载的网络资源比较多,对系统的体验性会差一点,而且用webpack打包的vuejs的vendor包会比较大.所以通过搜集网上所有对于vu ...
- Laravel大型项目系列教程(三)之发表文章
Laravel大型项目系列教程(三)之发表文章 一.前言 上一节教程中完成了用户管理,这节教程将大概完成发表Markdown格式文章并展示的功能. 二.Let's go 1.数据库迁移 文章模块中我们 ...
- Laravel大型项目系列教程(二)之用户管理
Laravel大型项目系列教程(二) 一.前言 本节教程将大概实现用户的注册.修改个人信息.管理用户功能. 二.Let's go 1.创建用户注册视图 $ php artisan generate:v ...
- Laravel大型项目系列教程(一)
Laravel大型项目系列教程(一) 一.课程概述 1.课程介绍 本教程将使用Laravel完成一个多用户的博客系统,大概会包含如下内容: 路由管理. 用户管理,如用户注册.修改信息.锁定用户等. 文 ...
- 推荐 Laravel API 项目必须使用的 8 个扩展包
如今在现代网络开发中,比较流行的模式是基于 API 开发,可以通过手机或网站来创建服务. Laravel 是创建基于 API 的项目的最佳框架之一,它为世界各地的大型社区提供了高速开发. Larave ...
- 记一次构建SaaS平台项目失败后的反思(收集的客户需求太少,且没有区分重点,闭门造车。技术演变要渐进)
记一次构建SaaS平台项目失败后的反思 前言: 笔者从2017年起开始着手将公司现有的软件系统改造成多租户模式,以降低整个系统的运营成本.但最后这个项目以失败告终.今天,我将对这个SaaS项目是如何走 ...
随机推荐
- Android Layout_weight 属性
Android 对Layout_weight属性完全解析以及使用ListView来实现表格http://blog.csdn.net/xiaanming/article/details/13630837 ...
- Android获取长按按键响应
Android获取长按按键响应http://www.2cto.com/kf/201312/261719.html Android下Listview的onItemClick以及onItemLongCli ...
- NIN (Network In Network)
Network In Network 论文Network In Network(Min Lin, ICLR2014). 传统CNN使用的线性滤波器是一种广义线性模型(Generalized linea ...
- opncv视频资料
链接: http://pan.baidu.com/s/1i37nXSL 密码: 3xnd这一套opncv资料包括视频和pdf资料
- Tensorflow Object_Detection 目标检测 笔记
Tensorflow models Code:https://github.com/tensorflow/models 编写时间:2017.7 记录在使用Object_Detection 中遇到的问题 ...
- POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)
http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...
- openstack kilo部署-基础环境
公司也想搞个私有云玩玩,于是展开了一系列的调研,部署测试,openstack 有几个版本真是坑爹!!,如果喜欢被虐有兄弟,你就试试 openstack 的 juno , icehouse等版本,用不了 ...
- Druid.io SQL乱码问题
1.场景 1.1.依赖版本 avatica-core 1.11.0 druid 0.12.0 1.2.问题重现: 使用Avatica JDBC查询语句:SELECT score FROM studen ...
- 选择Memcached还是Redis?
两者相似之处 Memcached与Redis都属于内存内.键值数据存储方案.它们都从属于数据管理解决方案中的NoSQL家族,而且都基于同样的键值数据模型.双方都选择将全部数据保存在内存当中,这自然也就 ...
- 37、使用FileInputStream和FileOutputStream读取和写入
绝对路径和相对路径 绝对路径:指文件在硬盘上真正存在的路径,比如:D:\Java\HelloWorld.java,这个指的是在电脑的d盘下的Java文件夹里面有个HelloWorld.java文件 相 ...