我們有一種情況,在開始時使用單個字符進行通配符搜索,然后在通配符之后使用其他字符進行搜索,并且運行速度非常慢(至少在 c# 中)。是否有原因和改進方法?在幾乎所有其他情況下它都更快。
20k 長隨機字串運行 1000 次的示例:
- a.*r1 所用時間:1802
- r1.*a 時間:9
- r1.*b.*c 所用時間:9
- r1f.*b.*c 所用時間:16
- a.*r1f.*c 耗時:3199
- a.*r1.*c 所用時間:1895
- a.*b.*r1f 所用時間:55450
它絕對不是隨機字串,因為嘗試過不同的字串。
模式肯定是,如果第一部分是單個字符,后跟通配符后面的任何字符,則它總是慢得多。
- 更新 -
我想知道 Regex 的作業方式是否是它回圈查找該單個字符,當它找到它時,它會搜索直到結束尋找下一個模式。當它沒有找到它時,它會回傳到第一個字符并開始尋找下一個第一個字符,直到它再次找到第一個匹配項并執行一些完整的邏輯,即使它可以跳過它在第一次運行時傳遞的所有那些字符.
我想我已經通過生成一個沒有字符“a”的隨機字串來確認這一點——如果我然后使用這個字符作為第一個字符它真的很快,但如果我使用“c”它很慢。在這種情況下,iea*b.*r1f 是即時的,但 c.*b.*r1f 需要很長時間。
如果是這樣想知道您是否可以以某種方式在正則運算式中優化它?
uj5u.com熱心網友回復:
這種性能差異的原因在于搜索優化的方式。
當模式以文字字符開頭時,在正則運算式引擎的“正常行走”之前使用快速演算法來查找字串中模式可能成功的可能位置(文字子字串所在的位置)。然后正則運算式引擎僅在這些位置測驗模式。
這就是為什么以字母開頭的模式a,對于不包含字母 'a' 的字串(無論大小)很快就解決了(沒有匹配,整個模式從未被測驗過)。
現在為什么對于同一種模式,以字母開頭的模式a(只有一個文字字符)和以 開頭的模式在abcd大多數情況下在隨機字串中表現出不同的表現。答案很簡單,具有四個字符abcd的位置比只有a. 嘗試的位置更少 => 結果更快。
另請注意,類似的模式a.*b.*c稱為病理模式,因為它可能導致回溯步驟數量的潛在爆炸。如果使用非貪婪量詞有時可能會減少問題,則不能保證它總是能提高性能(這不是魔杖)。最好的方法始終是使用適當的字符類、適當的量詞和最準確的字串描述來做到最精確,盡可能避免使用.*或.*?。a[^b]*b[^c]*c例如。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/390170.html
上一篇:DTO是否應包含列舉
