【正文】
,它嘗試對左輸入內(nèi)存中的每一個組元進行匹配,以找到滿足 BetaNode 的約束。這些匹配的元素通過網(wǎng)絡(luò)向下傳播。當(dāng)一個組元達到左輸入節(jié)點時,對稱的行為發(fā)生。 如下圖所示: 圖 . Beta Node 當(dāng)在 BetaNode 內(nèi)存中的元素數(shù)量越來越多時,匹配過程開始變慢,因為每一個到達的新元素需要為給定的約束在相對的內(nèi)存中嘗試匹配所有元素。當(dāng)數(shù)千個Fact 被設(shè)置到 working memory 中時,這將變成一個嚴(yán)重的限制。 解決問題的一個方法是在元素到達 BetaNode 內(nèi)存時對元素進行索引,這樣不需要為了發(fā)現(xiàn)匹配而遍歷相對內(nèi)存中的所有元素。 示例,如果有如下規(guī)則 : rule find brothers when p1: Person( $mother : mother ) p2: Person( mother == $mother ) then // do something end 如果沒有使用索引,每一個設(shè)置到 working memory 中的 Person 對象將嘗試匹配之前設(shè)置進來的所有 Person 對象,查看是否有同樣的 mother。因此如果之前已經(jīng)有 1000 個 Person 對象在 working memory 中,如果我們再設(shè)置進來一個新的Person 對象,它需要與之前的 Person 對象進行 1000次匹配。 如果我們使用“ mother”屬性對 BetaNode 內(nèi)存進行索引,當(dāng)新的一個 Person對象設(shè)置到內(nèi)存時,它只需要匹配之前有相同 mother屬性的對象(有相同 mother屬性的可能不只是 Person 對象,因此要進行匹配)就行了,通過索引可以非常高效率的完成這個過程。經(jīng)過索引,如果在一個新的 Person 對象之前只有他的一個兄弟 Person 對象存在,則它只要匹配這一個對象就行了,避免了其它 999次失敗嘗試。 Drools 正如上面所說的實現(xiàn)了對 BetaNode 的索引,以提高性能。 BetaNode 索引是默 認啟用的,用戶通常不需要去擔(dān)心它。雖然,在某些特殊情況下,用戶可能受限于系統(tǒng)內(nèi)存或其它原因不想啟用索引功能,索引可以單獨在各內(nèi)存上被禁止,通過設(shè)置如下的系統(tǒng)屬性: 例 : ..當(dāng)你在啟動應(yīng)用時 =false =false . 索引性能調(diào)整 理解當(dāng)索引啟用時發(fā)生了什么的一個好辦法是分析數(shù)據(jù)庫系統(tǒng)。眾所周知,索引是非常重要的提升數(shù)據(jù)庫查詢性能的機制,但是也增加了在 insert、 update 和delete 這樣的操作時的負擔(dān)。另外,也會引起內(nèi)存的消耗。對于大多數(shù)企業(yè)應(yīng)用來說一個計劃良好索引編排是基本要求,這通常是數(shù)據(jù)庫管理員的責(zé)任。一旦所以被定義,當(dāng)查詢被執(zhí)行后,一個查詢計劃組件被數(shù)據(jù)庫系統(tǒng)用來評估運行該查詢的最佳性能的辦法,有時使用索引,有時不用。 Working memory 在這點上有著同樣的問題和同樣的思路。 Drools 實現(xiàn)一 個自動的索引策略來建立 BetaNode 內(nèi)存的索引。為了通過一些數(shù)據(jù)讓我們可以更好的理解它,將使用“ Manners 64 benchmark”測試用例在“ Pentium IV 3 Ghz HT 1GB memory”的機器上的執(zhí)行情況來說明問題。這里的并不是一個詳細的基準(zhǔn)測試,只是一些簡單的概括,使得你更容易理解。 Manners 64 無索引 : 135000 毫秒運行時間 Manners 64 使用 BetaNode 索引 : 10078 毫秒運行時間 顯然在建立索引上花費的時間遠遠小于為運行時帶來的性能收益 。這里我們不分析內(nèi)存受限環(huán)境。 每個系統(tǒng)有它自己的特性,有時候它可能可以對性能作出更好的調(diào)整。例如在“ Manners 64 example”測試中,如果我們關(guān)閉右輸入內(nèi)存索引,我們可以獲得下面的結(jié)果 Manners 64 僅使用 BetaNode 左輸入內(nèi)存索引 : 142020 毫秒運行時間 以上甚至比不使用索引更糟糕。發(fā)生這種情況的原因在 Manners 64 中很容易看出,左輸入索引的消耗大于可以獲得的好處。因此如果我們反過來,啟用右輸入索引而關(guān)閉左輸入索引,我們獲得下面結(jié)果: Manners 64 僅使用 BetaNode 右輸入內(nèi)存索引 : 8765 毫秒運行時間 現(xiàn)在我們獲得了最佳效果。對于 Manners 64 來說,最佳方案是關(guān)閉左索引,保留右索引。 . 重新安排約束條件順序 另一個提高性能辦法的提示是,當(dāng)編寫規(guī)則時,盡量將嚴(yán)格的約束條件放在相對不嚴(yán)格的約束條件前面。例如,如果有如下規(guī)則約束: Employee (department == $aDepartment, name == $aName) 將 name 放在 department 前面會帶來更好的效率,因為 name 的約束條件更加嚴(yán)格。 Employee (name == $aName, department == $aDepartment) (除非你工作在一個部門比人員更多的組織中,這時可以考慮將 department 放在前面 ) 另一些增強正在被開發(fā),將在未來版本中進行說明。 . 大型 Ruleset 對于本節(jié),巨大的 RuleSet 定義如下: ? 1500 – 小型 ruleset ? 5002020 – 中型 ruleset ? 2020+ 大型 ruleset ? 10,000 – 巨大型 ruleset 在某些情況下,規(guī)則引擎不得不處理超過 50萬 或 100 萬條規(guī)則。這些情況是在智能 AI 系統(tǒng)中,其中的規(guī)則引擎在執(zhí)行時將產(chǎn)生新的規(guī)則,術(shù)語和 Fact。這些討論超越了本文檔考慮范圍。當(dāng)前描述主要集中在商業(yè)規(guī)則上。 第一件事情是考慮為什么有如此多規(guī)則,是否可以通過重寫規(guī)則來解決問題。有很多問題可以尋找。 ? 是否規(guī)則有很多常量值被硬編碼在條件中 ? 是否域模型有一個超過 100 列的巨大電子表格 ? 是否絕大多數(shù)規(guī)則共享相同條件 ? 是否邏輯可以被分解到不同階段 如果你對這 4 個問題的任何一個可以給出肯定答復(fù),那也許有機會通過改變規(guī)則來解決問題。管理 100,000 甚至 1,000,000 規(guī)則是非常讓人頭疼的,盡量避免它。檢查規(guī)則,并看看是否向下面例子所示。 If == abcd == basic ..... Then // do something 上面規(guī)則示例的基本問題是,規(guī)則有太多硬編碼值。如果每個客戶平均有 50個規(guī)則, 4 萬客戶就會有 200 萬條規(guī)則。讓我們使用更具體的例子說明: If == peter == level2 == jackie chan Then remend movies with jackie chan If == peter == level2 == jet li Then remend movies with jet li 查看示例,第一個問題是“這些規(guī)則是 否應(yīng)用到所有 Customer”,如果確認是,則規(guī)則中的第一個條件 是無意義的。因為所有的規(guī)則的這個類型都有該條件。雖然 accountId 更改了,規(guī)則可以有效地忽略它。如果我們在這重寫規(guī)則,規(guī)則可以用來支持任何客戶像 jackie chan 和 jet li。 If == level2 == jackie chan Then remend movies with jackie chan If == level2 == jet li Then remend movies with jet li 我們這樣做的原因一目了然。在規(guī)則中包含客戶的 accountId 硬編碼沒有任何好處,因為我們只希望規(guī)則引擎評估激活的部分。我們不希望將所有 Customer 都裝載到規(guī)則引擎中。接下來我們更進一步,讓規(guī)則更加通用化。 If == level2 ?id // 綁定 到變量 ?id // 通過綁定變量查找 favorites 的列表 Then remend all items in the favorites 通過這樣的改變,能夠顯著的減少規(guī)則的數(shù)量。這也是 Rete 路徑通常被稱為“數(shù)據(jù)驅(qū)動路徑”的原因之一。讓我們在這個示例上更進一步,定義 customer 的 type屬性從 level1 到 level10。假設(shè)我們運行一個百萬級的 在線商店,客戶可以在每一個分類(書,影碟,音樂,玩具,電子產(chǎn)品,服裝等等)中定義他們自己的喜好。如果對每一個客戶在分類中有不同的級別,會發(fā)生什么事情?如果使用硬編碼,將不得不增加更多的規(guī)則。如果我們改變規(guī)則,使它更具有通用性,同樣的規(guī)則可以處理多個分類。 Say we run a mega online store and customers can define their favorites in each of the categories (books, videos, music, toys, electronics, clothing). What happens if a customer has different levels for each category. Using the hard coded approach, one might have to add more rules. If we change the rule and make it more generalized, the same rule can handle multiple categories. If ?lvl // 綁定 remendation level 到 lvl 變量 ?rcat // 綁定 remendation category 到 rcat ?id // 綁定 account id 到 id ?id // 通過 id 找到 favorites 列表 ?rcat // 將 favorite 匹配到 remendation category ?lvl // 匹配 favorite level 到 remendation level Then remend all items in the favorites 如此看來,使規(guī)則具有動態(tài)性,并由數(shù)據(jù)驅(qū)動的價值在哪里呢?顯然,硬編碼規(guī)則要比讓規(guī)則具有通用性更快,但是會影響性能。在 ruleset 較小的例子中,使用,使用硬編碼可能對性能有輕微的提高。為什么會這樣?讓我們看一下兩種不同的規(guī)則 引擎:流程型( procedural)和 Rete 算法型 在一個流程型引擎中,一旦數(shù)據(jù)無法滿足在給定級別上的條件,引擎可以建立一個決策樹并且結(jié)束評估。當(dāng)規(guī)則數(shù)量增加時,流程引擎有許多的規(guī)則需要評估。在一個程序路徑上,規(guī)則必須按照最佳的順序排列,以獲得最好的結(jié)果。最佳順序排列方法的限制是,許多情況下無法對規(guī)則進行預(yù)先排序。如果我們使用一個RETE 規(guī)則引擎,硬編碼的規(guī)則導(dǎo)致與少數(shù)規(guī)則更少的關(guān)聯(lián)。當(dāng)規(guī)則數(shù)量增加時,單個規(guī)則的執(zhí)行更佳。通過對兩者評估,可以得到通用性的規(guī)則比硬編碼常量規(guī)則的速度更快。 [譯者注:上面這段 翻譯后不能清晰理解其含義,因此保留原文對照。 In a procedural engine, one can build a decision tree and end the evaluation once the data fails to satisfy the conditions at a given level. As the rule count increases, there are more rules the engine has to evaluate. In a procedural approach, the rules have to be sequenced in the optimal order to get the best results. The limitation of sorting the rules in optimal sequence is that many cases it39。s not possible to presort. If we use a RETE rule engine, the hard coded rules result in fewer joins for a small number of rules. As the rule count grows, the single rule will perform better. The equation to estimate the threshold where the generalized form is faster than hard coding the constants.] bn = 關(guān)聯(lián)節(jié)點 , lf = left facts, rf = right facts, ae = 對于隨機樣本的對象類型節(jié)點進行遞減評估的平均數(shù) [譯