uvp の1問目が 6.7秒縮みました — 「作ってから探し直す」をやめた話(UwView Pro v1.6.6.1)

技術解説

「1問目は ripgrep より2割ほど遅い」——そう書くつもりでした。 UwView Pro のコマンド uvp は、最初の検索で .uwvz(圧縮+索引)を作ります。作るぶん遅くなるのは当たり前で、そのかわり2問目から速い。そういう道具です。

ただ、記事に「2割」と書く前に、その2割が何でできているのかを測りました。すると、半分は負けなくていい負けでした。

結果

51.25GB の1本のファイル。.uwvz を消してから、sudo purge 後のコールドで3回測った中央値です(出力は /dev/null)。

50GB・1問目 時間 中身
ripgrep 15.2.0 54.94〜55.81秒 読みながら探す
uvp v1.6.6 65.7秒 .uwvz を作る 58.6秒 → 作った .uwvz で探し直す 約7秒
uvp v1.6.6.1 59.04秒 作りながら探す(作成 58.6秒・結果を出すのに 0.03秒)
(参考)uvp 2問目 6.6秒 .uwvz を探す。ripgrep の 8.4倍

65.7秒 → 59.04秒。6.7秒縮みました。 ripgrep との差は 約2割から、1.06〜1.07倍(6〜7%)までになりました。

何が起きていたか

v1.6.6 までの1問目は、2段になっていました。

  1. 元のファイルを読んで、.uwvz を作る(58.6秒)
  2. できあがった .uwvz を読んで、検索する(約7秒)

2段目の「約7秒」に見覚えがありました。表のいちばん下、2問目の 6.6秒とほぼ同じです。

当然で、2段目がやっていたのは2問目そのものでした。1問目の中に、2問目がまるごと入っていたわけです。

1段目で元のファイルを頭から終わりまで読んでいるのに、そのとき検索語を見ていない。読み終わってから、作ったばかりの .uwvz をもう一度開いて探す。素直に作ると、こうなります。「索引を作る」と「索引で探す」を別々の部品にしておけば、1問目は2つをつなぐだけで済むからです。

v1.6.6.1 でやったこと

読んでいる最中に、検索語も見るようにしました。

1段目で1行ずつ .uwvz に詰めていくとき、同じ行が検索語に当たるかどうかも確かめておく。読み終わった時点で、当たりはもう手元にそろっています。あとは並べて出すだけで、これが 0.03秒です。

$ uvp japan-latest.osm '東京' > /dev/null
creating japan-latest.osm.uwvz while searching …
created japan-latest.osm.uwvz while searching in 58.6s

1問目では、このように「作りながら探している」と出ます(2問目以降は .uwvz がもうあるので出ません)。

作る時間は 58.6秒のままです。圧縮や索引の作り方は何も変えていません。消えたのは探し直す分だけで、その差 6.7秒が、そのまま1問目の短縮になりました。

ちなみに、画面(GUI)のほうは先に同じ形になっていました。v1.6.6「First Light」で、索引の完成を待たずに検索を始めるようにしたときです。今回は、コマンドの側が画面に追いついた、ということになります。

それでも 6〜7% 遅い理由

59.04秒を読み出しの速さに直すと 828 MB/s。同じファイルを .uwvz を作らずに探す無料版の uvf は 962 MB/s なので、その 86% です。

残りの差は、圧縮する分と、5.74GB の .uwvz を書き込む分です。これは削れません——削ったら、2問目が 6.6秒で返ってこなくなります。

つまり1問目の遅れは、いまは全部が「2問目のための支払い」になりました。v1.6.6 までは、それに「しなくていい探し直し」が上乗せされていた、ということです。

出力をファイルに書く場合は、もう少し差が開きます。検証用のスクリプトで、当たった行をファイルに書き出して照合したときの1問目は、3GB 3.74秒/10GB 12.18秒/50GB 63.55秒でした(ripgrep の 1.13倍/1.09倍/1.14倍)。上の 59.04秒との差 4.5秒は、書き出しと照合の分です。

どう使い分けるか

  • 同じファイルを1回だけ調べる → 無料の uvf で足ります。.uwvz を作らないので、ripgrep と同等の速さです(実測まとめ)。
  • 同じファイルに何度も戻るuvp です。1問目で 6〜7% 払えば、2問目から 50GB を 6.6秒で探します。

v1.6.6.1 で変わったのは、この「払う分」が、払う必要のある分だけになったことです。

測り方

  • ファイル: OpenStreetMap 日本の XML、51,254,526,392 バイトの1本(japan-latest.osm
  • 語: 東京(94,979件)
  • 1問目は .uwvz を消してから、sudo purge 後のコールド/usr/bin/time -p で3回測った中央値(59.04/59.02/60.07秒)。出力は /dev/null
  • ripgrep 15.2.0 の 54.94〜55.81秒は、同じ機械・同じファイル・同じ条件の実測値の幅
  • v1.6.6 の 65.7秒と内訳(作成 58.6秒+探し直し)は、同じ条件で3回測った中央値
  • Mac M4/メモリ32GB/外付け USB SSD(素読み 約950MB/s)。秒数は環境によって変わります

UwView Pro は こちら(買い切り $129 / 月額 $9・14日間の無料試用つき)。
無料版の UwView(uvf)は GitHub Releases から入手できます。Mac は brew install --cask amru195704/uwview/uwview、Windows は Scoop(scoop bucket add uwview https://github.com/amru195704/scoop-uwviewscoop install uwview)でも入ります。

タイトルとURLをコピーしました