我正在使用bouncer来满足我的ACL需求,自从将项目从laravel 5.7升级到5.8以来,我注意到处理请求的时间大大增加了。
我正在处理两个模型(我们将它们称为Parent
和Child
),以及经过身份验证的用户对其的权限。
// Takes about 110ms. Eager loads various nested relationships and counters with specific constraints
$parents = Parent::myScope(...)->get();
// Bottleneck. Takes 5 minutes (!). Used to take about 40 seconds on laravel 5.7
$parents->each(function ($parent) {
$parent->permissions = [
'edit' => auth()->user()->can('edit', $parent),
'delete' => auth()->user()->can('delete', $parent),
'restore' => auth()->user()->can('restore', $parent)
];
$parent->children()->each(function ($child) {
$child->permissions = [
'edit' => auth()->user()->can('edit', $child),
'delete' => auth()->user()->can('delete', $child),
'restore' => auth()->user()->can('restore', $child)
];
}
}
我要附加这样的权限,因为$parents
变量将作为json发送到前端。我很确定这个实现是错误的,并且必须有更好的替代方法,但是真正的问题是加载时间莫名其妙地增加了五倍。
使用Debugbar
度量获得时间。
在monitor
中使用redis-cli
命令(我正在使用Redis
来缓存权限),我注意到GET请求的发送速度比以前慢。实际上,即使我停止了页面的加载( ESC ),对Redis的GET请求也不会立即停止。我不确定这是否是正常行为。
我试图在保镖仓库中检查问题,但没有发现任何东西。
答案 0 :(得分:1)
您要拨打auth()->user()
数百次。您可以尝试只调用一次吗?
$user = auth()->user();
$parents->each(function ($parent) use ($user) {
$parent->permissions = [
'edit' => $user->can('edit', $parent),
'delete' => $user->can('delete', $parent),
'restore' => $user->can('restore', $parent)
];
$parent->children()->each(function ($child) {
$child->permissions = [
'edit' => $user->can('edit', $child),
'delete' => $user->can('delete', $child),
'restore' => $user->can('restore', $child)
];
}
}
此外,由于您渴望加载children
,因此您不应在每次循环迭代中再次获取它们:
$parent->children()->each(function ($child) {
// ^^ remove these parentheses
$child->permissions = [
'edit' => $user->can('edit', $child),
'delete' => $user->can('delete', $child),
'restore' => $user->can('restore', $child)
];
}
答案 1 :(得分:0)
经过一些测试,找到了解决方案。事实证明,代码根本没有问题。
服务器出了点问题。我们不知道确切是什么,但是尝试在新安装的计算机上运行项目摆脱了那些糟糕的处理时间。 (现在的时间是在首次请求时15秒)
从laravel 5.7迁移到5.8之后,服务器的问题碰巧变得更糟,这导致了我的追逐。
添加
罪魁祸首是Xdebug。我们用它来进行代码覆盖率分析,但是性能太差了,最终还是切换到了phpdbg。