FPS on ニコニコプレイヤー・・・の復活

ちょっと要望があったので、先日一度書いて消した記事を一部復活させておきます。と言っても原文は手元に残ってないので、思い出しながらのまとめ的なものだけ。

FPS on ニワン語

実験プログラム↓

0::/a = drawText(text:"■", x:0, y:0, pos:"hidari ue", color:0x0000FF);
0::/i := 0; while_kari(i < 1000, timer(timer:i * 0.02, then:a.x++; a.y++); i++);

ニワン語を50FPSで動かして50FPSキャプチャして計測。(50FPSなのはニワン語では60FPSを正確に刻めないため)
結果↓

<フルスクリーン時>
3f→2f→3f→2f→以下繰り返し
<非フルスクリーン時>
3f→2f→5f→3f→2f→5f→以下繰り返し

結論、新プレイヤーでのニワン語は20FPS。(確か昔は15FPSだったはず?)
50FPS / 20FPS = 2.5fのため、3fと2fを繰り返しているのは正常。しかし非フルスクリーン時の挙動が謎。たんたんたんうん。

ニワン語と描画

通常のゲームプログラム(アニメーションプログラム)の基本構造はこのようになっています。

LOOP
    計算処理
    ↓
    描画処理
    ↓
    (必要に応じてスリープ処理)
LOOP-END

しかし、よくよく考えるとニワン語で描画処理の命令は書いていません。となるとニワン語を実行しているActionScript側で描画処理を行っていると思われますが、では一体どのタイミングで描画が行われているのか。
考えられるのは二つ。
<パターン1>

LOOP
    【ニワン語】計算処理
    ↓
    【ActionScript】描画処理
    ↓
    (必要に応じてスリープ処理)
LOOP-END

<パターン2>

LOOP
    【ニワン語】計算処理
LOOP-END

別スレッドで
LOOP
    【ActionScript】描画処理
    ↓
    (必要に応じてスリープ処理)
LOOP-END

そこで実験。

0::/a = drawText(text:"■", x:0, y:0, pos:"hidari ue", color:0x0000FF);
0::/i := 0; while_kari(i < 1000, timer(timer:i * 0.02, then:j := 0; while_kari(j < 1000, j++); a.x++; a.y++); i++);

1フレーム内に、フレーム間隔に収まらない処理を入れて意図的に処理落ちさせます。その時、こうなるはず。

パターン1の場合 → 処理落ちが発生する(1フレームでの移動量はそのままに、描画間隔が遅れる)
パターン2の場合 → 描画抜けが発生する(1描画間隔内で複数フレーム分の移動をしてしまう)

で、結果は後者の方でした。
すなわち、ニワン語の処理にかかわらず、ActionScriptは定期的に描画更新をしようとするようです。

ニワン語での効率的な描画

↑の結果を踏まえると、ニワン語の0.01秒刻みの命令体系は実はちょっと無駄です。

0.00::/(ニワン語の処理)
0.01::/(ニワン語の処理)
0.02::/(ニワン語の処理)
0.03::/(ニワン語の処理)
・
・
・
0.10::/(ニワン語の処理)

ここにActionScriptの描画処理を重ねるとこうなります。

0.00::/(ニワン語の処理)
・
・
・
0.04::/(ニワン語の処理)
ActionScriptの描画処理)
0.05::/(ニワン語の処理)
・
・
・
0.09::/(ニワン語の処理)
ActionScriptの描画処理)
0.10::/(ニワン語の処理)

つまり、0.00〜0.04の間の処理は全て適用済みの状況になって初めて一度だけ描画されるので、その間5回にかけて何度も計算するのは無駄になってしまいます。いえ、無駄なだけならいいですが、この場合処理量を5倍にしているわけで、むしろ積極的に損です。
よって、ニワン語ではプレイヤー側のFPSを強く配慮する必要があり、それに合わせて処理を書かないと大きくパフォーマンス的な損をしてしまうということです。この事を知らずに損をしているニワン語プログラマは結構多いのではないでしょうか?(言語仕様からだけだと100%わからない部分なので)




・・・確かこんな感じに書いたと思います。