「パソコンの速さはここ数年間で何倍にもなったのに,アプリケーションの体感速度はあまり変わらない」----筆者も含め,そう感じている方は多いはずだ。その最大の理由が,アプリケーションの機能や扱うデータの量が増えたことにあるのは間違いないところ。しかし筆者にはもう一つ理由があるように思う。

 それは,なまじある程度の速さで動くために,開発者がアプリケーションの実行速度を意識することが少なくなってきた,というものだ。

 もちろん,応答時間の定められた業務アプリケーションやゲーム,制御系プログラムなどの開発では,現在でも仕様を満たすまでパフォーマンス・チューニングを繰り返されているはずである。要求仕様を満たさない業務システムを納入するわけにはいかないし,反応が遅すぎるゲームはプレイすること自体が不可能になる。

 しかし,そうした明確な制限のないアプリケーションについては,「とりあえず動くから」という理由で高速化の努力を怠っているように思える。

高速化の努力を怠っているのでは?

 例えば,グラフィックスLSIが高速になった結果,見た目にわかるほど効率の悪いやり方で描画を行うアプリケーションが目につくようになってきた。スクロールのたびに画面全体を描き換える,というのがその例だ。Windows 3.xの時代なら,こうした方法ではとても実用に耐えなかったはずである。

 画面スクロールの場合,画面上にすでに存在する部分はビデオ・メモリー上のデータを使い,必要な部分だけを描画するのが鉄則だ。それでも遅ければ,メイン・メモリー上にあらかじめ1ページ分の描画内容をキャッシュしておく手もある。もちろん,その分のメモリーを余計に消費するようになるが,256MバイトのDIMMが3000円で買える今では高速化によるメリットのほうが上回る。

 メモリーの少ない環境に配慮するなら,ユーザーが描画方式を選択できるようにすればよい。ちなみに,アドビのAcrobat Readerでは「ページキャッシュを使用」オプションでページ・キャッシュを行うかどうかを設定できる。

 速度が命のゲームの場合も,プレイ中の速度には気を遣っているものの,起動時間やミッション/ステージのロード時間については無頓着なものを見かける。最近のゲームはインストール時に1Gバイト近くのミッション・データをすべてハード・ディスクにコピーするか,実行時にCD-ROMから読み込むようにするか,のいずれかを選ばせるものが多い。

 後者を選択した場合,同じミッションを繰り返す場合でもそのたびにCD-ROMからデータを読み込むため,毎回数秒~数十秒も待たされることになる。そのミッションがなかなかクリアできなかったりすると,本気で腹を立てるユーザーも少なからずいるはずだ。昔,CD-ROMのゲームが出始めたころは,現在プレイ中のミッションのデータをハード・ディスクにキャッシュするといった工夫をしているタイトルが多かったことを思うと残念である。

 確かに,ここに挙げた例は,実用上深刻な問題にはならない。しかしユーザーの使い勝手に影響を及ぼしていることは明らかだ。

わずかな努力でプログラムは速くなる

 プログラムの高速化は,多くの場合にソース・コードが読みにくくなったり,再利用性やメンテナンス性が悪くなるといった代償を伴う。そのためプログラミング作法に関する書籍にはたいてい,「多少速いコードを書くよりも,可読性や再利用性を重視せよ」と書いてある。しかし,こうした主張はその昔,速度至上主義のプログラマが多かったころに生まれたものであることに気を付けてほしい。

 当時のコンピュータでは効率の悪いコードを書いてしまうと,とても満足のいく速度で動作しなかったし,CPUタイムに応じて課金されるシステムでは,実行速度が運用コストにそのまま跳ね返る。当時のプログラマにとって,「速いプログラムを書く」というのは言われなくても当たり前のことだったのだ。速度よりも可読性のほうが大事というのは,あくまで過度な高速化を戒めるための言葉である。

 ところが,今ではこの言葉だけが独り歩きを始め,プログラムの高速化について語られることが減ってきたように思える。特に問題なのが,プログラマが実行速度を意識してコードを書くケースが少なくなっていることだ。機能を実現するためにどうすべきかに気をとられ,速度のことまで頭がまわらないのである。テストの際にも,我慢できないほど遅いわけではない,という理由でそのままにしておかれる。結果として,効率の悪いコードがいたるところに埋め込まれたアプリケーションが出荷されることになる。

 筆者は何もすべてのコードをぎりぎりまでチューニングすべきだと主張しているわけではない。今よりもほんの少しだけでよいから,速度を意識してはどうか,と言いたいのである。

 90-10(80-20)の法則によれば,アプリケーションの実行時間の90(80)%は,10(20)%のコードが占めている。このボトルネックとなる10%に多少の注意を払うだけで,アプリケーション全体の速度が大幅に向上する可能性がある。残りの部分はこれまで通り可読性や再利用性を重視してコーディングすればよい。

 では,ボトルネックとなる部分についてはどうするか。まず明らかに効率の悪いコードや非常識なコード,言い換えれば経験豊かなプログラマが「これはマヌケだ」と感じるようなコードは潔く書き直す。具体的には,先のスクロールするたびに全画面を描画するというのが一例である。

 また,「最近のプログラマのなかには,データベース・アクセスの際にカーソルやロックの種類(読み出し専用/書き込み),タイミングに注意を払っていない人が多い」といった類の話を取材先では聞く。雑誌のサンプルそのままに高機能なカーソルを使っていては,とりあえず動作するものの,速度面では大きなロスを招く。こうしたコードを残しておいたところで,可読性や再利用性は高まらない。まさに百害あって一利なしである。

 もう一つは,高速化によるメリットと,それに要する時間や人的資源などのコストを見極め,バランスよく高速化を図ることである。チューニングにかけた時間とその効果は,デバッグなどの作業と同様に対数曲線を描く。すでに十分高速化されたコードをさらに速くするのは大変だが,特に速度を意識せずに記述されたコードなら,わずかな変更で何倍も速くなることがある。

 CPUの速さは18か月で2倍にしかならないが,遅いコードと速いコードの速度差は,何倍から何十倍にもなることを忘れてはならない。

(山本 哲史=日経ソフトウエア)