大容量テキストビューア UwView(無料・OSS)の v1.2.1 を公開しました。
このバージョンは、中身のほとんどがブラウザ版(WASM)の修正です。先日の 無料版UVF(ネイティブ)とブラウザ版WASMの実測比較 では「速度は違っても機能は一通り動く」と書きましたが、その後に腰を据えて実利用テストをしたところ、表示そのものが壊れる不具合が続けて出てきました。本文が空になる、日本語入力にローマ字が混ざる、前後文脈に切り替えるとタブが固まる——どれもデスクトップ版では一度も起きなかったものです。
v1.2.0 は配布物のビルド後にこれらの修正が入ったため、公開せず v1.2.1 に差し替えました。ツールバーの全面アイコン化・セッション復元の修正など v1.2.0 の内容もすべて含まれています。
なぜブラウザ版だけが壊れたのか
原因の大半は、ファイルの読み方が根本的に違うという一点に行き着きます。
デスクトップ版は、OS のメモリマップドファイルでファイルを直接触ります。「10億行目の先頭バイト」を読みたければ、その場で読めます。読めないという状態がそもそも無い。
ブラウザ版にはその手段がありません。ローカルファイルは Blob として渡され、256KB 単位に切って非同期に取り寄せるしかない。つまり「読もうとした場所のデータが、まだ手元に無い」という状態が、日常的に発生します。
そしてデスクトップ版から持ってきたコードには、その状態を表す概念そのものがありませんでした。ここが今回の不具合のほぼ全ての震源です。
直したこと(ブラウザ版)
本文が表示されない/行番号がずれる
一番ひどかったのがこれです。行番号だけが並んで本文が空、…(省略) が大量に出る、検索結果一覧が空欄だらけ。しかもスクロールするほど悪化します。
原因は、「まだ届いていない」を「ファイルの終端」と誤って判定していたことでした。終端だと判断した以上、読めた内容(=空)は正しい結果ということになり、そのままキャッシュに焼き付いてしまいます。データが後から届いても、キャッシュを見に行くので直りません。
対処は2つです。未到着を明示的に検出して不完全な結果はキャッシュしない、そして届いた時点で描き直す。あわせて検索結果一覧は、行番号を経由せず行頭のバイト位置から直接読む方式に変えました(行番号を経由すると、未到着のときに別の行を読んでしまうため)。
この修正で、検索結果の行番号が実際とずれて表示される問題(5,000 行目が 4,865 と表示される等)も一緒に解消しています。原因が同じでした。
日本語入力でローマ字が残る
検索欄に「東京」と入力すると toukyou東京 になる、という分かりやすい不具合です。
これは UI フレームワーク(Avalonia)のブラウザ実装が、IME で変換している最中のキー入力を除外していないことによるものでした。フレームワーク側の問題なので、フレームワークに届く前に、ブラウザ側で変換中のキー入力を止める処理を足しています。変換を確定した文字だけが入るようになりました。
前後±N 表示でタブが固まる
検索結果一覧を「前後 ± 1」に切り替えると、ブラウザのタブごと固まることがありました。
全ヒットの行番号を求める処理が未取得のデータに当たると、「取得を要求 → 再計算 → まだ届いていない → また要求」と無限に回っていたのが原因です。WASM は単一スレッドで動くため、この手のループは画面ごと止まります。
行番号の算出を非同期化し、結果を保持してやり直さない方式にしました。切り替えた直後はヒット行だけがすぐ出て、算出が済んだ時点で前後の行が追加されます。
語を選んでも、別の語が色設定の対象になる
ref を選択しているのに、色設定パレットの見出しが nd(一つ手前の語)になる、という食い違いです。
ブラウザ版では等幅フォントが使えず、同梱のプロポーショナルフォントに切り替わります。にもかかわらず、語の選択処理だけが「1文字=固定幅」で座標を計算していました。クリック位置から語を特定する処理も、選択枠を描く処理も、両方ずれます。検索ハイライトと同じ実際の描画幅による計算に統一し、タブを含む行でもずれなくなりました。
読み込み・検索が遅い
計測してみると、検索処理そのものより、データの受け渡しの方が重いという状態でした。ブラウザとプログラムの間でバイト列を1バイトずつ変換していたためです。22MB のファイルなら、約2,300万回の変換になります。
メモリ領域へ一括コピーする方式に変えました。参考までに、修正前の実測(22.4MB・40万行・ヒット400件)はこうでした。
| 処理 | デスクトップ版 | ブラウザ版(修正前) |
|---|---|---|
| 読み込み(索引構築) | 19〜28 ms | 473 ms |
| 検索 | 4〜5 ms | 531 ms |
修正後の数値は、ブラウザのタブ制御の影響で当方の環境では安定した計測ができておらず、未計測です(体感では明確に速くなっています)。ここは正直に書いておきます。
ブラウザ版でも効く共通修正が2件
WASM 固有ではありませんが、ブラウザ版でも同じように直っているものです。
スクロールバーを末尾までドラッグすると画面が真っ白になる。 スクロールバーの上限値に総行数をそのまま入れていたため、末尾で表示開始行が範囲外(40万行のファイルで「先頭 400,001 行目」)になっていました。上限を1画面分引いた値に修正しています。デスクトップ版でも起きていた不具合です。
検索結果一覧のスクロールが重い。 一覧の作りが UI の仮想化(見えている行だけを扱う仕組み)の要件を満たしておらず、ヒット件数分の行を毎回すべて生成していました。100万件ヒットなら100万行です。メイン画面と同じ自前描画方式に置き換え、可視行だけを描くようにしました(実験で、修正前100万件生成 → 修正後0件)。ついでに、一覧側がマウス左ボタンの入力を先に奪っていたために左ドラッグでスクロールバーのつまみを掴めなかった問題も解消しています。
あわせて、結果一覧を閉じて開き直しても、表示位置と「前後 ± N」を引き継ぐようになりました(従来は毎回初期化)。
残っている制約
ブラウザ版には、今回でも直せていない構造的な制約が2つあります。どちらも書いておきます。
タブを背面にすると処理がほぼ止まります。 ブラウザが非表示タブの処理を抑制するためで、フレームワークが画面更新に同期して処理を進める設計であることも重なっています。大きなファイルを扱う間は、タブを前面にしておいてください。デスクトップ版にこの制約はありません。
ネイティブ版との速度差は残ります。 1億行のファイルで索引が約35倍、全文検索が約15〜20倍という差は、実測記事のとおりです。ファイルアクセス方式の違いによる構造的な差なので、今回の高速化で埋まる種類のものではありません。
裏を返せば、ブラウザ版の価値は速度ではなく「インストール不要で、その場で一通り動く」ことにあります。今回の修正で、ようやくその「一通り」が名実ともに揃いました(ただし、100万行程度なら快適に動くと思います。このテストはあくまでも1億行の話です)。
まとめ
- v1.2.1 は中身のほとんどがブラウザ版(WASM)の修正。本文が空になる/行番号がずれる/IMEでローマ字が残る/前後±Nでフリーズする/語の色設定対象がずれる、の5件を解消
- 不具合の震源はほぼ1つ。「データがまだ届いていない」という状態がコードに存在しなかったこと
- 読み込み・検索のデータ受け渡しを、1バイト単位の変換から一括コピーへ変更
- スクロールバー末尾の白画面と、検索結果一覧のスクロールの重さも解消(デスクトップ版にも効きます)
- 残る制約は「背面タブで停止」と「ネイティブとの構造的な速度差」の2つ
ブラウザ版は WASMデモ からインストール不要で試せます(Chromium 系ブラウザ推奨)。デスクトップ版は GitHub Releases またはダウンロードページからどうぞ。
関連記事
- 同じUwViewでも速度はどれだけ違う? — 無料版UVF(ネイティブ)とブラウザ版WASMを同一ファイルで実測
- 検索結果を独立ウィンドウに分離した理由 — ジャンプ・保存・前後文脈まで「見ながら」触れるフィルタPopup
- UwView Ver1.1.1 — 右クリックで即色分け、開き直せば前回の続きから
- UwView をGitHub公開 — Windows95時代の大容量テキストビューアを最大2億行・全OS対応にリニューアル
出典
- amru195704/UwView(GitHub) https://github.com/amru195704/UwView
- UwView Releases(v1.2.1 リリースノート) https://github.com/amru195704/UwView/releases
- ブラウザ版(WASMデモ) https://amru195704.github.io/UwView/
上位版:UwView Pro(発売中・全OS対応:Windows/macOS/Linux)
「巨大ファイルをいつでも瞬時に表示・検索、索引を保存して2回目以降は行番号付きで瞬時に開く・検索が最大約9倍・ログを約1/9で保管してそのまま開ける」商用版です。買い切り $129 / 月額 $9。
→ https://uvp.y42u.net/pro/
開発者より: アプリ・Kindle本・オープンソースの一覧は GitHub: amru195704 にまとめています。
お願い
本記事の情報は参考目的で掲載しており、正確性・完全性を保証するものではありません。機能・数値は各時点の確認で、今後のアップデートで変わる可能性があります。誤記・不正確な情報がございましたら、コメント欄よりご指摘いただければ、確認のうえ修正いたします。


コメント