Akira's Commentary

VNCの動作原理

VNCのサーバとクライアント(ビューワ)とは VNCプロトコルで接続されます。 VNCでビューワがTHINクライアントなのは、

  • セッションの初期化でクライアント側に都合のいいピクセル形式を 要求することができる。
  • 画面更新の通知が単純で、どのような環境においても 簡単に実現することができる。

ため、クライアントを簡単に実現できるようになっているためです。

画面更新の通知がどれだけ簡単かといいますと、 サーバからの通知は

座標(x、y)に矩形を描画しなさい

だけしか存在していません。 座標と矩形領域の表現方法にはいくつかの方法(エンコーディング)があり、 それによって、このような単純な描画プリミティブだけでも、 そこそこの描画性能がでるようになっています。 しかし最終的には矩形領域の描画さえ可能であればビューワが実装できるのです。

矩形の描画は、その矩形にどのようなデータを描画するのかによって

  1. サーバから送られてきたイメージデータ
  2. 画面上の他の矩形領域のコピー
  3. サーバから指示された色で塗りつぶす

の3種類の処理が必要です。しかしこれらの処理はどれも ビットマップ表示可能なディスプレイにとっては基本的な処理で、 (速度を気にしなければ)ごく簡単に実現できるものです。

VNCの、ある意味で革命的な点は、このような単純なプロトコルでも それなりに実用に耐えるシステムを構成することができる、ということを 実証したことでしょう。 それまでのリモートデスクトップシステムは、例えばXプロトコルが そうであるように、描画速度の向上のために結構複雑なプロトコルに なっています。Xプロトコルを知っている人からみると、 VNCプロトコルは非常識なものに思えるのではないでしょうか?

では、なぜVNCのような単純なプロトコルでも実用に耐えるのか。 それは、実際にユーザがデスクトップを使う場合の特性、および、 多くのアプリケーションがどのように描画しているのか、 に理由があります。

まず、ユーザが普通にデスクトップを使っている場合には

  • デスクトップはそれほど頻繁に更新されるものではない。
  • ある時点で更新されるのはデスクトップのごく一部分にすぎない。

という特性があります。つまり、多くの場合にはVNCのような 単純なプロトコルでも充分間に合う程度しか画面は更新されていない、 ということです。

VNCはこのような使い方を想定していますので、 ユーザが普通ではない使い方をすると破綻してしまいます。 典型的な例では、ムービークリップの再生とか、ゲームなどが相当します。 さすがに、VNC経由で動画をみたり、 ゲーム(特にアクションゲーム)をしよう、というのには無理があります。 ただ、これは、VNCだけではなく、 リモートデスクトップシステム全般にいえることです。 Xでもネットワーク経由でムービーの再生やアクションゲームを しようとするのはかなりきついでしょう。

さて、もうひとつの理由は、実際にアプリケーションが どのような描画を行なうか、という点です。 ここではXのアプリケーションと比較して見てみることにしましょう。

Xプロトコルには確かに豊富な描画命令を持っていますが、 多くのアプリケーションは、それらのごく一部しか使用していません。 そして、それらのよく使われる描画命令については、 VNCでの矩形描画とたいして性能が変わらないのです。

Xでよく使われる描画命令というと、

  1. 矩形領域の塗りつぶし
  2. 矩形領域のコピー
  3. イメージデータの表示
  4. 直線の描画
  5. 文字の描画

あたりがあげられると思います。

すぐに気が付かれるかと思いますが、矩形領域の塗りつぶしや、 コピーは、VNCにも存在している描画命令です。 こららの処理については、プロトコルが単純な分、 むしろVNCの方が早く実行できることになります。

もちろんこれは単純な塗りつぶし、コピーを行なう場合です。 Xではタイルパターンやラスタオペレーションを指示して、 背景付き、演算付きの塗りつぶし、コピーが可能です。 VNCではこのような処理はできませんので、 イメージ、矩形列で転送されることになり描画性能はかなり低下します。

イメージデータも同様です。イメージデータを表示しようとする場合には、 何らかの方法でイメージデータを転送する必要があります。 イメージデータの転送については、 VNCでもXでも同じ程度のネットワーク帯域、描画処理が必要になります。

最近のいわゆるクールなアプリケーションでは、 Xの描画命令では直接実行できないような効果が多用されていて、 それらは多くの場合、イメージデータとして描画されています。 このような点でもXとVNCとの性能差が縮まることになるわけです。

あとは直線と文字の描画、ですが、残念ながらこれらについては、 VNCではXほどの性能はでません。 Xでは直線、文字、ともにプリミティブとしてサポートされています。 しかし、VNCではこれらをイメージデータ あるいは矩形の集合として表現しなければなりません。 そのためどうしても性能は低下してしまいます。 ですが、その性能の低下は思ったほどひどいものではありません。

まず直線についてですが、もっとも多く使われるのは、 固定色で水平/垂直の直線の描画でしょう。 このような直線は特殊な矩形とみなすことができます。 ですから、たいていの場合は、VNCの(サーバ指定の色での) 矩形描画で間に合うことになります。

しかし斜めの線や、タイル、スティップル付きの線では どうしても遅くなります。このためアナログ時計などは、 単純なアプリケーションの割にXとVNCとでずいぶんと 負荷が違うのが判ります。

さて、最後に文字についてですが、多くの場合には、 固定色の背景の上で、小さ目の文字を使っていることと思います。 このような使い方であれば、 VNCでも比較的高速に描画することができます (まあXに較べるとずっと遅いのですが)。

固定色の背景の上で固定色で文字が描画された場合、 実は描画された領域の大半は同じ色の背景で、 その上の一部の部分だけ、異なった色が存在していることになります。 そう、VNCでは文字は(たいていの場合ですが)、 背景色の矩形と、文字を構成する矩形の列に変換して送られてきます。

VNCでもっとも効率の良い矩形のエンコーディング(Hextile)では、 矩形領域は2バイトで表現されます。 文字が小さくグリフが単純であればそれほど性能は低下しません。 ただ、大きな文字を描画しようとする場合、 ネットワーク上のデータ量は、Xでは文字の大きさに関係なく一定ですが、 VNCでは文字が大きくグリフが複雑になればなるほど データ量が増大して性能が低下していきます。

ですが、大きな文字を多数、高速に描画することはあまりありませんので、 多少の速度の低下を我慢すればVNCでも役に立つわけです。

さてそれでは、VNCが単純なプロトコルながら 使用条件さえ合えばそこそこ使いものになることが判ったところで、 実際のプロトコルの詳細をみてみることにしましょう。