我最近研究分析了在 SWIS上面创建的项目的性能。令人惊讶的是,最耗费性能的方法之一是优秀的  spatie/laravel-permission 包造成的。

经过查阅更多资料和研究,发现一个可能明显改善的性能问题 。既然解决方案已明确阐述,就很容易编写代码改善,提交请求。

现在这个解决方案已被合并和发布,下面是这个性能问题的分析和如何在自己的项目避免这类问题。

TL;DR: 跳转到结论部分.

性能瓶颈

如果我们抽象的看 spatie/laravel-permission 它主要做两件事:

  1. 保持一个属于某个模型的权限清单。
  2. 检查某个模型是否具有权限。

第一点说是性能瓶颈有点牵强。这里的权限数据存放在数据库中,需要的时候将会被读取出来。这个过程是有点慢但也只是执行一次。结果会被缓存下来,后续的请求可以直接使用。

第二点在性能瓶颈的观点上来看确实是一个瓶颈。 这个瓶颈取决于权限的性质和项目的大小, 因为权限会被频繁的检查。 在这个检查的过程中任何的迟钝都会成为整个项目的性能瓶颈。

过滤集合类

过滤权限集合的方法被认为是造成低性能的原因。 它做了如下事情:

$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 指出这些性能问题,我才有机会对其进行调查和纠正。

链接

更多现代化 PHP 知识,请前往 Laravel / PHP 知识社区

记一次对 Laravel-permission 项目的性能优化的更多相关文章

  1. Web项目开发性能优化解决方案

    web开发性能优化---安全篇 1.ip验证 2.操作日志.安全日志.登录日志 3.SQL注入校验 4.权限管理 5.验证规范(前端.后端.数据库约束) 2014-10-29 08:04   2773 ...

  2. vuejs项目性能优化总结

    在使用elementUI构建公司管理系统时,发现首屏加载时间长,加载的网络资源比较多,对系统的体验性会差一点,而且用webpack打包的vuejs的vendor包会比较大.所以通过搜集网上所有对于vu ...

  3. vue-cli3项目搭建配置以及性能优化

    项目初始化 注意:安装前请确保有安装node.js,并且node>=8.9 全局安装vue npm install -g @vue/cli 如果之前安装了vue旧版本,查看vue --versi ...

  4. vue项目性能优化总结

    在使用elementUI构建公司管理系统时,发现首屏加载时间长,加载的网络资源比较多,对系统的体验性会差一点,而且用webpack打包的vuejs的vendor包会比较大.所以通过搜集网上所有对于vu ...

  5. Laravel大型项目系列教程(三)之发表文章

    Laravel大型项目系列教程(三)之发表文章 一.前言 上一节教程中完成了用户管理,这节教程将大概完成发表Markdown格式文章并展示的功能. 二.Let's go 1.数据库迁移 文章模块中我们 ...

  6. Laravel大型项目系列教程(二)之用户管理

    Laravel大型项目系列教程(二) 一.前言 本节教程将大概实现用户的注册.修改个人信息.管理用户功能. 二.Let's go 1.创建用户注册视图 $ php artisan generate:v ...

  7. Laravel大型项目系列教程(一)

    Laravel大型项目系列教程(一) 一.课程概述 1.课程介绍 本教程将使用Laravel完成一个多用户的博客系统,大概会包含如下内容: 路由管理. 用户管理,如用户注册.修改信息.锁定用户等. 文 ...

  8. 推荐 Laravel API 项目必须使用的 8 个扩展包

    如今在现代网络开发中,比较流行的模式是基于 API 开发,可以通过手机或网站来创建服务. Laravel 是创建基于 API 的项目的最佳框架之一,它为世界各地的大型社区提供了高速开发. Larave ...

  9. 记一次构建SaaS平台项目失败后的反思(收集的客户需求太少,且没有区分重点,闭门造车。技术演变要渐进)

    记一次构建SaaS平台项目失败后的反思 前言: 笔者从2017年起开始着手将公司现有的软件系统改造成多租户模式,以降低整个系统的运营成本.但最后这个项目以失败告终.今天,我将对这个SaaS项目是如何走 ...

随机推荐

  1. CH暑假欢乐赛 SRM 07 天才麻将少女KPM(DP+treap)

    首先LIS有个$O(n^2)$的DP方法 $f(i,j)$表示前i个数,最后一个数<=j的LIS 如果$a_i!=0$则有 如果$a_i=0$则有 注意因为$f(i-1,j)\leq f(i-1 ...

  2. 【bzoj4337】【Bjoi2015】树的同构

    题解 无标号树的HASH: 找到树的重心,以重心为根求出括号序列: 由于树的重心最多只有两个,取字典序的最小括号序列HASH即可 树的括号序列$s_{u}="(s_{v_{1}},s_{v_ ...

  3. C/C++:文本查询(单词查询)

    如题: C/C++: Textqurey.h(方便看都在.h里实现了): // // Created by 徐爱东 on 17/7/10. // #ifndef TEXTQUERY_TEXTQUERY ...

  4. 在Kubernetes集群里安装微服务DevOps平台fabric8

    转载于https://blog.csdn.net/wzp1986/article/details/72128063?utm_source=itdadao&utm_medium=referral ...

  5. paramiko修改本分源码

    一.获取paramiko源码 环境:Python3 下载地址:https://github.com/paramiko/paramiko 使用的是 demos这个文件夹 二.修改部分源码用以登入 2.1 ...

  6. Zabbix应用四:Zabbix监控Nginx

    利用Zabbix监控Nginx 一.准备nginx监控模版: 1.1.下载nginx监控模版:  点此下载 1.2.导入模版: Zabbix管理页面,选择'配置'->'模版'->'导入': ...

  7. JVM体系结构和工作方式

            JVM能够跨计算机体系结构来执行Java字节码,主要是由于JVM屏蔽了与各个计算机平台相关的软件或者是硬件之间的差异,使得与平台相关的耦合统一由JVM提供者来实现.   何为JVM   ...

  8. IOS取消performSelector警告

    #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks&quo ...

  9. 悬浮按钮css

    .floating-button { color: #fff; position: absolute; right: 16px; bottom: 88px; width: 56px; height: ...

  10. 数据结构编程实验——chapter8-采用树结构的非线性表编程

    关于树结构的非线性表编程在数据结构中可以说占据了半壁江山,其中涉及的知识点繁杂,但也是数据结构体现运算优化的核心所在,下面我们将较为初步且系统得讨论数据结构中一系列有关树的表示. 首先我们再次明确树的 ...