サーバーサイドとクライアントサイド、グラフはどちらで描画すべきか?
サーバーサイドの場合、.pngファイルなどの形式でグラフの画像を作り、掲載するページに埋め込むのだが、その画像はスクリプトを使ってデータと軸のラベルを設定し色を決め凡例を作り画像の大きさを定めた上で出力される。
クライアント側で描画する場合は、同様のパラメーターとデータをクライアントに送り、クライアント側で描画する。描画にはJavaScriptがよく使われる。しかし、グラフを掲載するWebページを配信する際に送るのはデータとパラメーターだけではない。描画に使われるJavaScriptとカスケード・スタイル・シートのライブラリーも送る必要がある。両方式には、次表に示す長所と短所がある。
長所短所 | サーバーサイド | クライアントサイド |
---|---|---|
長所 |
|
|
短所 |
|
|
オープンソースの世界には、一方または両方の方式が可能なクラス・ライブラリーがある。簡単な例としては、サーバーサイド・ライブラリーではlibchart、クライアントサイト・ライブラリーではWebfx Chartingがある。どちらもPHPスクリプトに組み込むことができ、出力とコードの例が公開されている。コーディングに必要な作業量も同程度だろう。以下、両方式の長所短所を比較するため、このライブラリーを使って行ったテストの結果を紹介する。これは、両ライブラリーが生成するグラフの品質を比較するものではない。また、Javaなどを使う方法もあるが、ここでは考慮していない。
両方式の選択で考慮すべき条件は、配信に必要な帯域幅と実処理時間の2点に集約される。一般に、帯域幅の定量化は比較的容易だ。したがって、サーバー管理者は帯域幅に正式な上限を設定する一方、共用サーバー上の処理時間については、過大な負荷を負わせたウェブマスターの利用を制限する権利を保持しつつ、各自の良識に任せている。どちらについてもサーバー管理者を満足させておくことは、ウェブマスターにとってもよいことだ。
ダウンロードする量
まず、クライアント・マシンでグラフを描画する場合に必要なコード量を検討しよう。サーバーサイドの場合、コードは次のようにきわめて短い。
<img src='mypic.png'/>
一方、クライアントサイドの場合は、少なくとも次のコードが必要だ。
<script type="text/javascript" src="../includes/excanvas.js"></script> <script type="text/javascript" src="../includes/chart.js"></script> <script type="text/javascript" src="../includes/iecanvas.js"></script> <script type="text/javascript" src="../includes/canvaschartpainter.js"></script> <link rel="stylesheet" type="text/css" href="../includes/canvaschart.css" /> </head><body onload="ieCanvasInit('../includes/iecanvas.htc');"> <div id="chart1" class="chart" style="width: 1000px; height: 250px;"></div> <script type="text/javascript"> function draw1() { var c = new Chart(document.getElementById('chart1')); c.setDefaultType(CHART_LINE); c.setGridDensity(10,10); c.setVerticalRange(-5131,66880); c.setHorizontalLabels([JS array of labels]); c.add('Current production','#4040FF',[JS array of data points]); c.draw(); } </script> <script type="text/javascript"> window.onload = function() { draw1(); }</script>
空白とデータを除いて800字超。そのうち450字はグラフを表示するごとに繰り返す必要がある。サーバーサイドの場合の22文字に比べ、無視できない量だ。
次に、データを検討しよう。クライアントサイドの場合は数字の配列になるだろう。データが整数で数が少なければ配列は小さくて済み、ほとんど無視できる量だ。それでは[123456.7890,123456.7889,…,2.6]のような倍精度ならどうだろうか。送信する際に小数点以下を切り捨てて整数にすることも考えられるが、精度が若干犠牲になり、クライアント側でデータを再利用する場合に問題が生ずる可能性がある。データ数200、各11字として分離記号(カンマ)を含めると、全体で約2,400字となる。
以上の条件でグラフを1つ描画する場合をまとめると、およそ次のようになる。
サーバーサイド(バイト) | クライアントサイド(バイト) | ||
---|---|---|---|
htmlのコード | 22 | htmlのコード | 400 |
ライブラリー | 0 | ライブラリー(キャッシュがなくページごとに1回ロード) | 66,000 |
画像 | 25,000 | 描画のコード | 450 |
データ | 0 | データ(グラフ1枚の概数) | 2,400 |
合計 | 25,022 | 合計 | 69,250 |
この場合、グラフ1つを描画する際に必要なダウンロード量はクライアントサイドの方が大きくなる。1つのページで5つの異なるグラフを描画する場合は次のようになる。
サーバーサイド(バイト) | クライアントサイド(バイト) | ||
---|---|---|---|
htmlのコード | 100 | htmlのコード | 400 |
ライブラリー | 0 | ライブラリー(キャッシュがなくページごとに1回ロード) | 66,000 |
画像 | 125,000 | 描画のコード | 2,250 |
データ | 0 | データ(グラフ5枚の概数) | 12,000 |
合計 | 125,100 | 合計 | 80,650 |
グラフが5つになると、ダウンロードするパッケージはクライアントサイドの方が小さくなる。明らかに、ダウンロード量はグラフの数に大きく依存する。この数字は些細なものに見えるが、このページが何千回も送信されれば、その総計は帯域幅の上限からみて無視できないものとなる。
CPUの負荷
次に、CPU負荷について検討する。前掲のサーバーサイド・クラス・ライブラリーはフリーのgdライブラリーを使っている。サーバー管理者はこの種のライブラリーはプロセッサー資源を大量に使用し共用サーバーでは大きな問題だと考えているが、本当に、サーバー側で描画した方がCPU負荷は高いのだろうか。
それを見るため、スタンドアロンのシングルプロセッサー・サーバー(CPUは2.8GHzハイパースレッド対応Intelプロセッサー、RAMは2GB)でテストし、top
を使って測定してみた。このテストでは、MySQLを使って200のデータからグラフを描画するPHPスクリプトを2本用意した。3つのグラフをそれぞれ28KBの.png画像として作成するものと、JavaScriptで描画するものだ。測定したCPU負荷にはMySQLによるものも含まれているはずだが、データベースの処理はどちらも同じため、今回の比較では考慮する必要はない。
結果 | GD → .png | JavaScript |
---|---|---|
ページのロードに要した秒数 (*ダイヤルアップ) |
15 | 3 |
CPU負荷 | 約5秒、平均10%増加 | 約3秒、平均3%増加 |
ダウンロード量 (ソースコード、その他) |
28K×3=84K | 8K+66K=74K |
まとめ
グラフは重要かつ情報量の多い表現方法だ。1つのグラフは千語に匹敵すると言えよう。しかし、ウェブ・コンテンツとする場合は、グラフを画像として送るときと千語として送るときとの長所短所を比較検討する必要がある。データを送りJavaScriptを使ってローカルで描画すれば、利用者にとってページのロードが速くなるだけでなく、サーバーのCPU負荷を約3分の1に抑えることにもなる。
Colin Beckingham フリーランスのプログラマー、ライター。東部オンタリオ在住。現在、オープンソース・リソースを利用してバイオマス燃焼装置の運転を記録しグラフにするプロジェクトに参加している。