タグ: 正規表現
- 作成者投稿
- 2024年11月7日 12:06 am #32056yasuji参加者
江村様
いつもお世話になっております。
yasujiです。[検索]の正規表現検索を実行した際の検索完了時間について質問があります。
質問している理由は、検索モードを[正規表現]に設定して、様々な検索をしていた際に、時々異常なまでに短時間で検索が完了することが過去にあり、いくつも試した結果おそらく[正規表現]については、[検索する文字列]の文字の種類に対応して、検索アルゴリズムを自動的に切り替えて検索を実行しているという推測をしたので、それが本当かどうかの確認をしたいためです。
※ここにおいての検索モードとは、[検索]ダイアログの中にある[(無し)]、[正規表現]、[エスケープシーケンス]、[数値範囲]を指しています。(呼び方がわからないため)(Q1)
検索モードが、[(無し)]、[エスケープシーケンス]の場合は、江村様独自のCPUの拡張命令SSE2などを使用したアルゴリズムで高速に検索処理されるように見えます。
検索モードを[正規表現]に設定して、[検索する文字列]を「feed」と設定して[次を検索]を実行すると、実際は検索モードの[(無し)]の検索アルゴリズムを自動選択して検索を実行していると考えていますが正しいでしょうか?
検索モードを[正規表現]に設定していた場合に検索アルゴリズムの[(無し)]を自動選択する条件は、「記号を含まない文字列」だと推測しています。
根拠は、「feed
」と正規表現として同一の検索結果になる「(feed)
」の検索処理時間を比較すると、圧倒的に「feed
」の方が高速になり、かつ検索モードを[(無し)]に設定した時と同一の検索処理時間になるため。(Q2)
検索モードを[正規表現]に設定して、[検索する文字列]を「\n
」と設定して[次を検索]を実行すると、実際は検索モードの[エスケープシーケンス]の検索アルゴリズムを自動選択して検索を実行していると考えていますが正しいでしょうか?
検索モードを[正規表現]に設定していた場合に検索アルゴリズムの[エスケープシーケンス]を自動選択する条件は、「\n\r\t
などのエスケープシーケンスの範囲内の記号のみとそれ以外の記号を含まない文字列」だと推測しています。
根拠は、「\n
」と正規表現として同一の検索結果になる「(\n)
」の検索処理時間を比較すると、圧倒的に「\n
」の方が高速になり、かつ検索モードを[エスケープシーケンス]に設定した時と同一の検索処理時間になるため。ここからが本題になります。
検索モードを[正規表現]に設定してかつ、スレッド数(メインメニュー[ツール(L)]->[カスタマイズ(C)…]の[カスタマイズ]->[高度]->[スレッド数(N)])との関係について確認したいことがありますが、経験的に[正規表現]の検索動作が検索する文字列の内容により変わることがわかっていて、正規表現ライブラリ(Boost.Regex, Onigmo)を使用した検索処理に限定したいため、上記の質問を私の認識が正しいかの確認の意味でしました。質問の前提の使用環境と使用ファイルは、下記のとおりです。
〔使用環境〕
CPU : AMD Ryzen 9 3900X 12-Core Processor 3.80 GHz (12 Core, 24 Thread)
RAM : 128 GB
OS : Windows 10 Pro 64bit 22H2 build 19045.5011
MB : ASUS PRIME X570-PRO
〔使用ファイル〕
jawiki-20241020-abstract.xml.gz (file size: gz 260.8 MB, xml 2.3GB)を展開したXMLファイル(Q3)
[カスタマイズ]->[高度]->[スレッド数(N)]を 1 に設定して、下記の事前オプション設定をした[検索]で[検索する文字列]に「<[a-z]+>」を設定して[次を検索]を実行します。
—————————–
[検索]のオプションを設定
〔チェックボックス〕
[大文字と小文字を区別する(C)]:ON
[一致する文字列を数える(U)]:ON
上記以外のチェックボックスすべて:OFF
〔ラジオボタン〕
[正規表現(X)]:ON
[高度]
〔チェックボックス〕
[CRとLFを区別する(T)]:ON
[次を検索/前を検索で重ならない文字列のみ一致する(F)]:ON
上記以外のチェックボックスすべて:OFF
[正規表現エンジン(G)]:Boost.Regex
[正規表現で検索する追加行数(L)]:0
—————————–
進捗ダイアログが表示されて、「2,000 個見つかりました。1,239,000 / 20,871,119 行目を検索中。」のように、現在の検索が完了した行数が表示されます。
「1,239,000」と表示される位置の行数が、必ず1,000ごとか500ごとで更新されてています。別の言い方すると、検索完了の直前まで行数の下3桁の数値が「000」または「500」で固定されているように見えています。
なぜ、スレッド数が1であれば、確実に+1ずつの増加するにも関わらず、下3桁の数値が「062」や「489」などのように表示されることなく「000」または「500」の表示で固定されるのでしょうか?
内部処理で、設計通りの動作ができない未知の不具合または設計不備があるのではないかと懸念しています。
根拠は、[スレッド数(N)]を 2 に設定して、上記同様の検索を実行すると、「000」または「500」の表示に固定されずに表示されるため。(Q4)
[カスタマイズ]->[高度]->[スレッド数(N)]を 1 に設定して、(Q3)の「[検索]のオプションを設定」と同じに[検索]のオプションを設定し、[検索する文字列]に「<[a-z]+>
」を設定しておきます。
[次を検索]を実行して、ステータスバーの左下に検索処理時間が16.935秒と表示されます(ばらつきがあるのは理解しています)。[スレッド数(N)]を 2 に設定して、同じ検索条件で検索を実行すると、8.904秒と表示されます。
Notepad++は、ストップウォッチ計測で34.545秒でした。
EmEditorの1スレッドの検索処理時間は、Notepad++の2分の1以下です。ストップウォッチ操作による計測遅延を1.5秒程度と見込んでも処理時間の差が大きすぎます。
過去の正規表現に関する江村様の対応から考えてBoost.Regexの検索エンジンを改造して高速化していることは考えられません。また、Boost.Regexは単体では、UTF-8,UTF-16,UTF-32の文字エンコーディングとUnicodeのプロパティの正規表現に対応していません。それらに対応するためには、ICUライブラリと組み合わせる必要があります。Notepad++は、ICUを使わずに独自に追加実装して対応しているように見えます。
[スレッド数(N)]を 1 に設定してNotepad++の検索完了時間より2分の1も短いのは、実は内部では検索用スレッド数は、[スレッド数(N)]が 1 の場合は、その値に 1 を足したスレッド数 2 で検索しているのでしょうか?この質問をしている理由は、江村様のテキストエディター速度比較(英語版)の他のエディターとの検索性能比較においてEmEditor側の処理条件を合わせていない(不明)、正規表現検索について書かれていないため役に立ちませんでした。したがって、自力でBoost.Regexを使用しているNotepad++とEmEditorの処理の条件を合わせて、正確に性能比較を行いたいため(例えば、複数のガソリンスタンドのガソリン価格を比較するときに、$/Galと$/L の混合だと正しい比較ができないのと同じです)。
EmEditorがNotepad++と同じ処理条件になるためには、検索のスレッド数は1([カスタマイズ]->[高度]の[スレッド数(N)]は1)、テキストファイルはすべてメモリーに保存([カスタマイズ]->[高度]のディスクベースは無効)に設定する必要があります。
マルチスレッドで検索を高速化するのはEmEditorの機能でよいのですが、比較対象のテキストエディターは1スレッドで検索するので、12や24スレッドで検索を高速化するEmEditorには最初から勝てません。加えて言えば、フェアな性能比較ではありません。検索モード別にフェアな性能比較をした上で、マルチスレッドで検索を高速化するとこの性能になりますであれば問題ないです。——————
使用したストップウォッチアプリ(無償)
無料ストップウォッチ (Microsoft Store)
無料ストップウォッチ (Offical Site)2024年11月18日 9:57 am #32079Yutaka Emuraキーマスターいつもお世話になっております。江村です。
(Q1)
ご指摘の通りです。(Q2)
その通りです。(Q3)
500行ごとに進捗を更新するように最適化しています。不具合ではありません。(Q4)
検索用スレッド数が[スレッド数(N)]が1の場合、内部ではその値に1を足して2スレッドで検索しているのではないかというご質問ですが、これは考えられません。よろしくお願いいたします。
2024年11月18日 3:40 pm #32081yasuji参加者江村様
いつもお世話になっております。
yasujiです。ご回答ありがとございます。
(Q1)
ご指摘の通りです。(Q2)
その通りです。了解しました。
(Q3)
500行ごとに進捗を更新するように最適化しています。不具合ではありません。それでは、「根拠は、[スレッド数(N)]を 2 に設定して、上記同様の検索を実行すると、「000」または「500」の表示に固定されずに表示されるため。」と記載しましたが、[スレッド数(N)]が2の場合は、 下3桁の数値が「062」や「489」などのように表示されるのはなぜでしょうか?ご説明とこの場合の表示方法が一致しません。
(Q4)
検索用スレッド数が[スレッド数(N)]が1の場合、内部ではその値に1を足して2スレッドで検索しているのではないかというご質問ですが、これは考えられません。そうすると、EmEditorは、Unicode未対応のBoost.Regexの正規検索エンジンをどのようにUnicode対応させてNotepad++よりも高速に処理できるのでしょうか?
私の考えだと、(1)Boost.Regexのソースコードに改良加えてUnicode対応している、(2)Boost.RegexとICUの代わりを独自実装してUnicode対応しているのいずれかをしているのかと思います。
長年高速処理を追求し続けて改良を加えられているので、検索エンジンについても説明いただければ、大きなセールスポイントになると思います。よろしくお願いします。
- 作成者投稿
- このトピックに返信するにはログインしてください。