作成している WEB サービスで、データを1万件ほど表示する必要があった。
それまで作っていたスペックでは、せいぜい 100件程度だった。
HTML で小さなウィンドウを作り、その中を CSS 設定で縦スクロールするようにして、内部に 100件のデータを入れる。
まぁ、よく見るインターフェイスだ。
そのプログラムのまま、中身を1万件にしたら、いろいろと問題が出た。
まず、表示を指示してから実際に表示されるまでが遅い。
そして、表示されてから、スクロールしようとすると非常に重い。
1万件ものデータ処理だから遅いのかな、と思って、Javascript の速度を調べると、
データ処理には 100ms 程度しかかかっていなかった。
表示までは5秒程度かかったのだが、これらはほとんど、挿入された HTML の解釈時間だということになる。
いろいろ実験するも、1000件程度までは実用になるのだが、1万件になると実用的な速度ではない、と分かるばかりだった。
初期表示の遅さについては、まず 100件程度を表示してから、徐々に追加していったらどうだろう、とか試してみた。
確かに、すぐに表示はされるのだが、その後スクロール処理がどんどん重くなる。
1/10 秒ごとに 100件づつ追加、とかしていると、この追加のたびにかかる処理速度も、どんどん重くなっていく感じがする。
…うん、たぶんすでに表示しているデータ件数 n に対して、新たなデータを入れるときの処理速度が n*log n に比例しているのだ。
これ、プログラムしているとよく見る構造だ。つまりは、内部的に DB を構築していて、データ件数が多くなると挿入速度が遅くなっていく。
実際、HTML は内部で DOM ツリーというものを構築する。これはツリー構造の DB に他ならない。
何か操作を行うたびに、このツリーをたどり、どの部分を操作対象とすべきか、画面表示の対象とすべきか、などをチェックしていく。
ここら辺は、ブラウザ内部での処理の問題なので、Javascript で高速化できる問題ではない。
問題を棚上げして別の仕事をしていて、ふと気づいた。
そもそも、HTML の量が多いのが問題なのだ。Javascript 側は、1万件くらいなんてことない。
じゃぁ、HTML のコード量は最小にしよう。
先に書いたように、データの表示は小さなウィンドウ内で、スクロール表示になっていた。
1万件あっても、実際に表示されているのは 10件程度だった。
div のスクロールイベントにフックをかけて、現在のスクロール位置を取得する。
データは、1行1データのようにきれいに並んでおり、1行の高さも決まっていた。
なので、スクロール位置から、現在表示されるデータが何行目かも判断できる。
何行目を表示するかわかれば、それより「上」に何行あるかもわかる。これらは画面外のデータだ。
だから、HTML としては最小限に、全部をまとめて「高さだけ」をブラウザに伝えることにした。
div を作り、style で height を指定すればよい。
下方向も同じように、画面外は div 1つで済ませる。
そして、表示したい部分の10行ちょっとだけ、その場で生成してブラウザに渡す。
10行程度なので、ブラウザは瞬時に解釈を終え、遅延なく表示される。
上下に div を作っているのは、スクロールバーを「あたかも1万件のデータがあるように」表示するためだ。
でも、HTML には10件程度のデータしか入っておらず、スクロールするたびに書き換える。
実際には、そのプログラムでのデータ表示はこれほど単純ではなく、一部だけ行の高さが変わったりもしていた。
でも、規則性があるので div の「高さ」をそれに合わせて調整するような計算式を作った。
上端と下端の部分も、破綻しないようにプログラムする必要がある。
しかし、それらは些細なことだ。
大量のデータで HTML が遅い時の処理方法をネットで探していたが、あまり見当たらなかった。
DOM の遅さ、という話になると、単純なハンドリングの速度の話だけで、極端に多いデータの際にスクロールすら遅いのをどうにかできないか…というような話題にはならないのだ。
まぁ、個別論だから一般的に論じにくい、というのもあるとは思うが。
今回の例では、スクロールのたびに DOM を大きく入れ替える、という「DOM が遅い」という話題ではやるべきでないことをしている。
でも、それによって HTML 量を極端に減らすと、DOM の処理速度は劇的に改善する。
…やっていて「時期尚早な最適化は害悪」という言葉を実感していた。
当初は、今までのやり方で何とかならないか、と最適化を試みていたんだ。
でも、どうにもならないと思って大きく作り変えたら、問題は簡単に解消した。
しかも、このプログラムは速くなるようになんて書いてない。
DOM 操作に jQuery とか使ってるし。
(古いプログラム部分が多いので、過去に作った部分はそのままなのです)
最適化を考える前に、根本原因が何かをちゃんと見極めよう、って話です。
同じテーマの日記(最近の一覧)
関連ページ
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |