Speed up multiline regexes anchored by `^`.
オープン
まだ誰も着手していません。
extension-modules
performance
topic-regex
type-feature
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
Feature or enhancement
Proposal:
I noticed that for regexes of the form
regex = re.compile("^foo", re.MULTILINE)
regex.search(...)
there's a character by character loop calling SRE(match) every iteration. That's significantly slower than the regex
regex = re.compile("foo...")
regex.search(...)
which does a special prefix scan for "foo" without having to call SRE(match) on each character:
I would expect ^foo and foo to have more or less identical performance. A simple patch like this fixes that.
diff --git a/Modules/_sre/sre_lib.h b/Modules/_sre/sre_lib.h
index df377905bfa..70de4cccefd 100644
--- a/Modules/_sre/sre_lib.h
+++ b/Modules/_sre/sre_lib.h
@@ -1855,6 +1855,18 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
return 0;
}
while (status == 0 && ptr < end) {
+ if (pattern[0] == SRE_OP_AT &&
+ pattern[1] == SRE_AT_BEGINNING_LINE &&
+ (void*) ptr > state->beginning &&
+ !SRE_IS_LINEBREAK((int) ptr[-1]))
+ {
+ /* fast-forward to the next newline character */
+ while (ptr < end && !SRE_IS_LINEBREAK((int) *ptr)) {
+ ptr++;
+ }
+ if (ptr >= end) {
+ return 0;
+ }
+ }
ptr++;
RESET_CAPTURE_GROUP();
TRACE(("|%p|%p|SEARCH\n", pattern, ptr));
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs
- gh-148778
- gh-152339
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まずリンクされたPRを確認し、その後、Modules/_sre/sre_lib.h のSRE検索ループ、特に参照されているプレフィックススキャンコードを読みます。複数行の ^foo 検索とアンカーなしの foo 検索を再現し、パフォーマンスを比較します。正規表現の動作を変更せずに、アンカー付きの場合の速度が測定可能なほど近くなれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- performance
- issue の種類
- 機能追加
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 35/100