2015年4月19日日曜日

部分描画とスクロールバーの問題

テーブルタグも引用タグもその他全部のタグもとりあえずの実装は出来ました。本格的なデバッグは出来ていないので完成というのはまだ無理ですがマークダウンの実装は一区切りつきました。

この後はマークダウン表示ルーチンをアプリに組み込まなければいけないのですが、ずっとマークダウンのことばかりやっていたのでアプリの実装の詳細をかなり忘れてしまいました。組み込みにもまだ大きな問題が残っています。

いろいろ思い出さなければいけないので、なぜこんなにもマークダウンをズルズルとやる羽目になったのかちょっと書き出してみようかと思います。

もともと不具合がありました。これはWindowsの16bit時代からの名残か何かで、全体の高さが32767ピクセルを超えるとスクロールバーがそれ以上スクロールしなくなるというものです。300コメントを超えた当たりでこれが実際に起きるようになり、これへの対応に追われ続けて、まだ対応が終わっていないという状況です。

スクロールの範囲を広げるだけならスクロールルーチンを自作するだけなので別に難しいことはないのですが、問題は「300コメントを30000ピクセルに渡ってズラッと表示した後に、スクロールバーでスクロールする」というのが非常に動作が遅いというところにあります。それは私が「コメントに対してテキストボックスを作成し、300コメントなら300個のテキストボックスを縦に並べてズラッと表示する」という恐ろしいほどの手抜き実装をしているのが原因です。つまりこれは不具合というよりも、私の手抜きに対して必然的に生じた当然の帰結というべきものです。不具合というのは手抜きでもバグでもオブラートに包んで表せる便利な言葉ですが、それを隠れ蓑にするべきではありませんでした。まったく申し訳ないです。

300個のテキストボックスを並べるのは動作が非常に遅いです。それはテキストボックスというものが300個並べられることを想定して作られていないというようなことが原因だろうと思います。これを解決するためには部分描画が有効です。つまり必要な部分、たとえば132番目のコメントから描画を初めて、140番目のコメントで画面が全て埋まったらそこで描画をやめる、といったように画面に表示される部分だけ描画処理を行えば、全体がどんなに大きくても描画量を一定にすることが出来ます。この場合なら描画用アイテムは132から140までの9個で済みます。

そこからスクロールするのも簡単です。上に10ピクセルスクロールしたとしたら、131番目のコメントの下から10ピクセル分から描画を開始すればいいわけです。スマホのようなインターフェースであれば指でスクロールするだけなのでそれで問題ないのですが、この時問題になるのはスクロールバーです。

スクロールバーはスクロールできる全体の範囲を知っていることを前提にしたUIです。「これを描画した結果全体が何ピクセルになるか」を知っていないと正しく動かすことが出来ません。描画した結果何ピクセルになるかを知るためには描画に等しい負荷がかかることも多く、このスクロールバーの存在が原因で、大半のテキストエディタは1MBといったような、現代のCPUであれば二次キャッシュに乗ってしまうような小さな容量のテキストファイルを表示しただけでまともに動かなくなりますし、そうでないエディタは文字幅が一定のフォントを用い改行ケタ数を指定することでどうにか動かそうとします(それでもまともに動かないことも多いです)。

しかしスクロールバーはPC用アプリに必須のものなので削除することは出来ません。問題は「いかに効率よく描画後のサイズを知るか」というところにあります。そのためには「描画せずに描画後のサイズを知る」処理が必要になり、なかなか面倒です。しかしHTMLのテーブルタグを綺麗に配置しようとすれば、描画後の大きさをあらかじめ知ることが必須になりますので、どうせマークダウンのためにテーブルタグを実装するなら最初からマークダウンの処理を書いてしまえば良い、ということで作り始めたというのがあらましになります。

そして七難八苦があり、描画後の大きさを効率よく知ることが出来るルーチンが書けたように思います。ただ、まだ動かしていないのでわかりません。私がやったのは、動かす前に速く走るコードを書こうとする「事前最適化」と呼ばれるもので、プログラミングの世界では最も愚かな人間がやることとされています。「このコードは速く走るのか」ということを考えながら書くと普通に書くのの何倍も時間がかかりますし、普通に書いて実際にコードが遅くなるのか、その遅くなる原因はなにか、というところまで突き止めてからでないと、ほとんどの最適化の努力は空回りに終わります。現代のハードウェアでは、プログラマが思ったとおりにコードが実行されることは稀で、速く走るコードを書いたつもりで普通に書くより遅くなっているというのは非常によくあることです。

ただこの処理がボトルネックになるだろうというのは私なりの確信があります。「オバマ大統領だけどなにか質問ある?」といったサブミの2万ぐらいのコメントをストレスなく表示するためには、描画後の大きさをものすごい速さで計算することが必須になるでしょう。

そしてこれを「部分描画ルーチン」に組み込まなければなりません。部分描画ルーチンもマークダウンの実装を始めるより前の大昔に軽いテストしかしておらず、正しく動くかは分かりません。実際かなりややこしい処理になります。これがうまく動けば、とりあえずのブログ限定公開にこぎつけることが出来ると思います。

0 件のコメント:

コメントを投稿