2013年07月07日の日記です


Javascript の Canvas は結構遅い  2013-07-07 12:31:25  コンピュータ

TX-0 エミュの進捗。


自分で納得いくレベルまで出来上がったので、公開しようと複数ブラウザでの動作試験。

…遅い。


僕は Chrome 使いなので、納得いく速度で動いていた。

しかし、Chrome 以外のブラウザでは Canvas は非常に遅いらしい。


IE はまだ許せるレベル。FireFox は遅くて話にならない。


とはいえ、「Chrome 専用です」と公開するのは面白くない。出来るだけ多くのブラウザで動くようにしないと。

ただでさえ興味を持つ人が少ないエミュレータだと思うのに、「自分のブラウザでは動かない」で見てもらえないのは残念だから。


高速化の技法をあれこれ試してみる。

もっとも、当初は Chrome でも遅すぎて話にならず、ある程度高速化技法を使ってあるので、劇的には早くならない。




前提条件を書いておこう。


TX-0 のディスプレイは、511*511 の表示領域を持っていた。

この数字が中途半端に見える説明は今はしない。気になる人は TX-0 の記事を読むように。


さて、511 は現代のコンピューターには扱いづらいので、512x512 の canvas を用意する。

ここに、TX-0 の表示命令が送られたときに描画を行うわけだが…


TX-0 は、VRAM を持たない。というか、当時メモリは高価で、VRAM なんていう発想はなかった。

結果、CPU が直接座標を指定し、表示命令で点を一つ描くことになる。


座標を変えながら点を打ち続ければ、図形を描画できる。


でも、描いた点はすぐに消える。

ディスプレイの表面の蛍光体が、「ビームが当たるとしばらく光る」ようになっているのだけど、多分0.25秒~0.5秒程度で消えたと思う。


#当時の動画が残されていて、ディスプレイを撮影しているのだが、フリッカーが激しい。

 フリッカーが激しいということは、残光時間はそれほど長くなかった、ということだ。

 もっとも、映画カメラには移らなくても、人間の目は暗いあかりでも敏感にとらえられる。

 いろいろな条件を勘案し、0.25~0.5秒程度と推察した。



さて、現代のディスプレイは、1/60 秒程度の周期で描き変えられている。

残光時間もその程度だ、ということだ。TX-0 に比べて、はるかに短い。


だから、TX-0 エミュレータでは、残光時間の長いディスプレイ(長残光ディスプレイ)を再現する必要がある。


「だんだん光が暗くなっていくさま」も再現しようとすると、描画ドット数はその分だけ増加する。

残光時間を長くすれば、書き換えるドットも増えるため、さらに増加する。




一番動作が重かったプログラムは、「lightGunTst」と言うプログラムだ。


ひたすら「隣のドット」に点を描きつつ、その光がライトペンに拾われたときだけ、別のところにも点を打つ。

これだけのプログラム。


シンプルであるがゆえに、単位時間あたりに描くドットの数が多い。

メインループが6ワードしかないので…単純計算で、1秒に1万3千ドットほど書き込む。


画面は 1/60 秒ごとに書き変えるので、1回の「新しい」ドットは 230ドットほど。

残光時間が 0.25秒の設定だと、16段階に暗くなっていくドットを描く。全部で、描き変えは 3700ドット程度。


…というわけで、1/60 秒で 3700ドットを書き込めれば問題はないのだが、Chrome 以外の canvas では遅すぎてこれが難しい。


lightGunTst では、「隣のドット」にひたすら書いていくので、画面上の変更は局所的だ。

一種のダブルバッファで描画しているので、転送を最小限の面積にすると、少し処理速度が上がった。


これで、chrome はほぼ 60 FPS(Frame Per Second: 1秒の描画回数) 出る。

IE だと 58 程度で、遅くはなっているが許容範囲。


FireFox は非常に動作が不安定。

あまり描画速度が安定せず、30~50くらいの間でふらふらし続ける。




内部的には、動作開始からの実時間(マイクロ秒)と、TX-0 の内部的な「クロック」を両方計測していて、それぞれのフレームで「どこまで TX-0 の処理を進めてよいか」を判断している。


このため、描画が一瞬だけ遅くなった場合でも、次のフレームで内部処理が追いつくことがある。

ほぼリアルタイムに動作できる、ということだ。

(もっとも、TX-0 実機の速度を見たことがないので、TX-0 内部クロックの計算は資料をもとに想像しただけのものだ。だいたい動画とはあっているみたいなので、大きくは外していないと思う)


ただ、実時間はどんどん過ぎていくので、遅くなったために一度に計算する量が増えてさらに遅く…という悪循環を起こす可能性がある。

そこで、どんなに実時間から遅れても、1回の処理はTX-0 の 4000 クロック分まで、と上限を決めてある。


これは、通常の内部処理は 2777 クロック分なので、ちょっと多いくらい。

遅れた場合は少しづつ挽回してもよい、と言う程度。




lightGunTst 以外のプログラムは、内部処理も多いため、こんなに描画量は多くない。


そのかわり、描画も局所的ではなく、画面全体に及ぶようになる。

TX-0 が VRAM を持たない特性上、常に描画を「リフレッシュ」し続けるため、常に画面全体が描画されている状態になる。


描画が少ないために速度が上がるかと言うと、画面全体を常に転送し続けることになるので、あまり速度が上がらない。

なかなか微妙な問題だ。






ところで、一種のダブルバッファと描いたが、canvas に対して getImageData した配列に対して書き込みを行い、putImageData で実際の canvas に転送している。


canvas では「1ドットを描く」命令はない。かならず、1ドットの矩形を描くことになり、効率が悪い。実際測定しみると遅い。


配列に対して1ドットを描くのは、アドレスを計算して代入を行うだけ。

TX-0 は白黒2諧調なのだが、実際の画面の色は不明(資料がない。当時の写真もほとんど白黒)なので「オシロスコープの改造ディスプレイだから、緑」ということにしている。


そうなると、1ドットに4つある色情報のうち、緑だけ書き込めばよい。こうやって速度を稼ぐわけだ。




写真と言えば、少なくとも1枚はカラー写真がある。残念ながらディスプレイは点灯していないのだが。


コンソールの色などはなんとなくわかるので、その色に合わせてエミュレータの各種パネルを描いている。


…もっとも、絵心はないのですべてテキスト + CSS 。

完成後に、絵を描いてくれる人がいたら差し替えます (^^;




同じテーマの日記(最近の一覧)

コンピュータ

別年同日の日記

02年 手巻き時計

09年 大人がヘルパンギーナにかかると…

15年 どぜう

16年 ドナルド・ミッキー 命日(2007)


申し訳ありませんが、現在意見投稿をできない状態にしています


戻る
トップページへ

-- share --

0000

-- follow --




- Reverse Link -