摘要:我最近研究分析了在上面創(chuàng)建的項(xiàng)目的性能。經(jīng)過(guò)查閱更多資料和研究,發(fā)現(xiàn)一個(gè)可能明顯改善的性能問(wèn)題。在這個(gè)檢查的過(guò)程中任何的遲鈍都會(huì)成為整個(gè)項(xiàng)目的性能瓶頸。過(guò)濾集合類(lèi)過(guò)濾權(quán)限集合的方法被認(rèn)為是造成低性能的原因。使用代替可以提高的性能。
我最近研究分析了在?SWIS上面創(chuàng)建的項(xiàng)目的性能。令人驚訝的是,最耗費(fèi)性能的方法之一是優(yōu)秀的 ?spatie/laravel-permission?包造成的。
經(jīng)過(guò)查閱更多資料和研究,發(fā)現(xiàn)一個(gè)可能明顯改善的性能問(wèn)題?。既然解決方案已明確闡述,就很容易編寫(xiě)代碼改善,提交請(qǐng)求。
現(xiàn)在這個(gè)解決方案已被合并和發(fā)布,下面是這個(gè)性能問(wèn)題的分析和如何在自己的項(xiàng)目避免這類(lèi)問(wèn)題。
TL;DR:?跳轉(zhuǎn)到結(jié)論部分.
性能瓶頸如果我們抽象的看?spatie/laravel-permission?它主要做兩件事:
保持一個(gè)屬于某個(gè)模型的權(quán)限清單。
檢查某個(gè)模型是否具有權(quán)限。
第一點(diǎn)說(shuō)是性能瓶頸有點(diǎn)牽強(qiáng)。這里的權(quán)限數(shù)據(jù)存放在數(shù)據(jù)庫(kù)中,需要的時(shí)候?qū)?huì)被讀取出來(lái)。這個(gè)過(guò)程是有點(diǎn)慢但也只是執(zhí)行一次。結(jié)果會(huì)被緩存下來(lái),后續(xù)的請(qǐng)求可以直接使用。
第二點(diǎn)在性能瓶頸的觀點(diǎn)上來(lái)看確實(shí)是一個(gè)瓶頸。 這個(gè)瓶頸取決于權(quán)限的性質(zhì)和項(xiàng)目的大小, 因?yàn)闄?quán)限會(huì)被頻繁的檢查。 在這個(gè)檢查的過(guò)程中任何的遲鈍都會(huì)成為整個(gè)項(xiàng)目的性能瓶頸。
過(guò)濾集合類(lèi)過(guò)濾權(quán)限集合的方法被認(rèn)為是造成低性能的原因。 它做了如下事情:
$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();
這兩個(gè)代碼段實(shí)現(xiàn)了同一件事情,但第二個(gè)更快。
性能測(cè)試我正在開(kāi)發(fā)的應(yīng)用中大約有 150 個(gè)不同的權(quán)限。 在一個(gè)普通的請(qǐng)求中, 大約有 50 個(gè)權(quán)限需要用 ?hasPermissionTo?這個(gè)方法去檢查,當(dāng)然,有些頁(yè)面可能需要檢查大約 200 個(gè)權(quán)限。
以下是用來(lái)做性能測(cè)試的一些設(shè)置。
$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: 過(guò)濾,傳遞一個(gè)模型作為回調(diào) foreach($searchForTheseUsers as $searchUser) { $result = $users->filter(function($user) use ($searchUser) { return $user->id === $searchUser->id; })->first(); } # 方法 3: 過(guò)濾,傳遞屬性作為回調(diào) foreach($searchForTheseUsers as $user) { $searchId = $user->id; $result = $users->filter(function($user) use ($searchId) { return $user->id === $searchId; })->first(); }
以上三個(gè)方法都會(huì)被用來(lái)測(cè)試過(guò)濾 1 個(gè)屬性,2 個(gè)屬性,3 個(gè)屬性,所以,用方法 1 過(guò)濾三個(gè)屬性就會(huì)是這樣:
foreach($searchForTheseUsers as $user) { $result = $users ->where("id", "=", $user->id) ->where("firstname", "=", $user->firstname) ->where("lastname", "=", $user->lastname)->first(); }結(jié)果
方法 #1 | 方法 #2 | 方法 #3 | |
---|---|---|---|
1個(gè)屬性 | 0.190 | 0.139 (-27%) | 0.072 (-62%) |
2個(gè)屬性 | 0.499 | 0.372 (-25%) | 0.196 (-61%) |
3個(gè)屬性 | 0.488 | 0.603 (+25%) | 0.198 (-59%) |
我們可以得出結(jié)論:對(duì)一個(gè)項(xiàng)目而言,重復(fù)的過(guò)濾一個(gè)大集合會(huì)引發(fā)嚴(yán)重性能瓶頸。
多屬性的過(guò)濾明顯增加計(jì)算成本。
使用 Collection::filter() 代替?Collection::where() 可以提高60%的性能。
警告:傳遞完整的模型給過(guò)濾器回調(diào)是很耗費(fèi)性能的,最好是傳遞多帶帶的屬性。
致謝感謝 Spatie 和 spatie/laravel-permissions?的貢獻(xiàn)者創(chuàng)建如此優(yōu)秀的包,我非常喜歡使用!感謝 Andru Beldie?指出這些性能問(wèn)題,我才有機(jī)會(huì)對(duì)其進(jìn)行調(diào)查和糾正。
鏈接spatie/laravel-permission package.
Issue #550 addressing performance problem.
Pull request #710 that fixes problems.
更多現(xiàn)代化 PHP 知識(shí),請(qǐng)前往 Laravel / PHP 知識(shí)社區(qū)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28808.html
摘要:在大多數(shù)的開(kāi)發(fā)中,角色和權(quán)限的管理都是非常重要的一部分。上關(guān)于角色和權(quán)限管理的包有很多,今天就為大家介紹幾個(gè)好用的包。緩存在中,為了提高應(yīng)用的性能,或自動(dòng)的存儲(chǔ)角色和權(quán)限數(shù)據(jù)。 showImg(https://segmentfault.com/img/bVTEb3?w=2200&h=1125); 在大多數(shù)的web開(kāi)發(fā)中,角色和權(quán)限的管理都是非常重要的一部分。Laravel上關(guān)于角色和權(quán)...
摘要:初步分析提升可從兩方面入手,一個(gè)是增加并發(fā)數(shù),其二是減少平均響應(yīng)時(shí)間。大部分的時(shí)間花在系統(tǒng)與數(shù)據(jù)庫(kù)的交互上,到這,便有了一個(gè)優(yōu)化的主題思路最大限度的降低平均響應(yīng)時(shí)間。不要輕易否定一項(xiàng)公認(rèn)的技術(shù)真理,要拿數(shù)據(jù)說(shuō)話(huà)。 本文最早發(fā)表于個(gè)人博客:PylixmWiki 應(yīng)項(xiàng)目的需求,我們使用tornado開(kāi)發(fā)了一個(gè)api系統(tǒng),系統(tǒng)開(kāi)發(fā)完后,在8核16G的虛機(jī)上經(jīng)過(guò)壓測(cè)qps只有200+。與我們當(dāng)...
摘要:手頭做的項(xiàng)目開(kāi)發(fā)得差不多了,而打包配置是一開(kāi)始粗略配置的,不大的項(xiàng)目打包出來(lái)得,所以現(xiàn)在必須進(jìn)行優(yōu)化。用于生產(chǎn)環(huán)境的打包,設(shè)置其為后,這些庫(kù)會(huì)提供最小體積的文件。這種情況打包后的體積要更小一些。最后打包結(jié)果的體積開(kāi)銷(xiāo)主要就是以上幾項(xiàng)。 手頭做的項(xiàng)目開(kāi)發(fā)得差不多了,而打包配置是一開(kāi)始粗略配置的,不大的項(xiàng)目打包出來(lái)得6MB+,所以現(xiàn)在必須進(jìn)行優(yōu)化。 打包結(jié)果分析 執(zhí)行命令 webpack ...
摘要:記錄一個(gè)前端項(xiàng)目?jī)?yōu)化的路程,效果如上圖。第二步優(yōu)化結(jié)果再次運(yùn)行查看項(xiàng)目打包情況可以看到項(xiàng)目體積已經(jīng)優(yōu)化到,中也看不到的蹤影了。本文主要想提供一些優(yōu)化思路及手段,即如何定位通過(guò),查看頁(yè)面加載時(shí)間問(wèn)題,然后再解決這些問(wèn)題。 showImg(https://segmentfault.com/img/bVbq282?w=381&h=384); 記錄一個(gè)前端項(xiàng)目?jī)?yōu)化的路程,效果如上圖。 接下來(lái)我...
摘要:記錄一個(gè)前端項(xiàng)目?jī)?yōu)化的路程,效果如上圖。第二步優(yōu)化結(jié)果再次運(yùn)行查看項(xiàng)目打包情況可以看到項(xiàng)目體積已經(jīng)優(yōu)化到,中也看不到的蹤影了。本文主要想提供一些優(yōu)化思路及手段,即如何定位通過(guò),查看頁(yè)面加載時(shí)間問(wèn)題,然后再解決這些問(wèn)題。 showImg(https://segmentfault.com/img/bVbq282?w=381&h=384); 記錄一個(gè)前端項(xiàng)目?jī)?yōu)化的路程,效果如上圖。 接下來(lái)我...
閱讀 2064·2021-09-07 10:14
閱讀 1494·2019-08-30 15:53
閱讀 2282·2019-08-30 12:43
閱讀 2875·2019-08-29 16:37
閱讀 768·2019-08-26 13:29
閱讀 2016·2019-08-26 13:28
閱讀 451·2019-08-23 18:33
閱讀 3539·2019-08-23 16:09