VS CodeのMarkdown PDFで出力されるHTMLを自作エディタで開いたら急にフリーズしたのでなんで?ってなったんですが、どうやらファイルの1行に32万文字のjava scriptがあって行末移動しようとすると固まりました…。
前々から横移動は遅いの知ってたんですが、やっぱり考えさせられることになりました。
今は横移動は特に速度対策はしていなくて、単純に頭から順番に文字幅を計測して表示しています。
現在の仕様
簡単にですが現在の仕様です。
- 1って書いてある左側が今表示している画面です。
- 32万文字目って書いてる右側がこれから表示する画面です。
- Aはこれから文字を描画する開始位置(ルーラーの開始位置)です。
移動処理
例えばENDキーを押すと行末に移動するんですが、下記で処理するようにしています。
- 最初に32万文字目までの文字幅を算出します。
- 次に上記1.から画面の表示幅を引きます。
- 上記2.をルーラーの文字幅(数字0の幅)で割ってAを算出します。
どーしてもAの位置を求める必要があるんですがフォントが等幅フォントならAの位置ってすぐにわかるんですが、プロポーショナルフォントの場合、文字幅は計算しないと分からないので頭から検索して算出しています。もちろん、同じ文字は幅計算しなくていいようにキャッシュしています。
実際の遅さ
今だとだいたい32万文字移動で1分くらいかかります。
試しに世界最速エディタでも確認してみました。はい。サクサク移動しますね。困ったなぁ。こうやって整理したらいい解決策が見つかるかなと思ったんですが、まったく出てきませんね。
100文字単位とかでキャッシュしたら速くなるとか思ったんですが、一番最初は全部の文字幅を計算しないとダメっぽいしなぁ。もしかしてファイルを開いた時点で100文字分を纏めてキャッシュしてます?
どこに時間がかかるのか?
確認していたテキストは1行に10万以上が多数あったので32万文字の1行で3回実行して確認してみました。するとだいたい8秒~9秒くらいかかることがわかりました。ほとんどが描画ですね。
文字幅の算出は GetTextExtentPoint32W を利用しています。そして、その文字幅は文字をキーに Dictionary に保持しています。
対応策
どーしましょうね。普通に考えたら1行が32万文字とかあんまないので無視でもいいんですが、できることなら改善したいですね。多分サクサクは無理っぽいですが。
コメント