描画速度
SwingとAWTで違うの?というはなし。JOGLとかはとりあえず考えない。
描画の実行は、repaint()を呼び出すか、getGraphics()でGraphicsをとってきて自分でsync()する(アクティブレンダリング)という選択肢がある。
repaint()は遅延する(遅延した分はまとめて一回にされる)?みたいなので、ゲームとかで明らかにカクカクしてるのにFPSを出すと予定通り、という事がおこる。Macではおこった。
一方アクティブレンダリングだとFPSは正確にだせるはず。
たぶん。
あとSwingはデフォルトでダブルバッファリングするので、自前でバッファ作んないでいいのかな?
参考
- Java GUIプログラミングの、とてもBasicなFAQ(翻訳物)
- http://homepage1.nifty.com/algafield/JavaGUIFaq19j.html
- Javaでゲーム作りますが何か?
- http://javagame.main.jp/index.php?%A5%A2%A5%AF%A5%C6%A5%A3%A5%D6%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0
- WisdomSoft ダブルバッファリング
- http://wisdom.sakura.ne.jp/system/java/swing/swing8.html
とりあえずいまテストした感じでは、AWTでもSwingでも速度は大差ないな…。AWTはFrameにCanvasをのせて、SwingはJFrameにJPanelで実装した。MacOSX10.4 でjava -versionは
java version "1.5.0_07" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164) Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)
ちなみにMacだと、AWTで自力ダブルバッファ使わなくてもちゃんと出力される。Windowsだと普通にちらつくけど。
windowsでちょっと試したら、SWINGの方が少し速かった。
ゲーム作るならSwingで自力ダブルバッファなしアクティブレンダリングあり、がいいのかな。
上限60FPSで640x480にランダムな矩形を毎フレームたくさん描くプログラムで試してみた。
AWTはどちらも自力ダブルバッファ、Swingはrepaint()は自力ダブルバッファなしで直書き、アクティブレンダリングは自力ダブルバッファ。
マックでの結果は
GUI | 矩形の数 | repaint() | アクティブレンダリング |
AWT | 500 | 60FPS | 53FPS |
AWT | 2000 | 60FPS | 16FPS |
Swing | 500 | 60FPS | 55FPS |
Swing | 2000 | 60FPS | 18FPS |
こんな感じ。
repaint()の方が速いけど、画面はあきらかにカクカクしている。もちろんアクティブレンダリングもカクカクしてるが。
つまり内部での実行速度的には60FPSだけど、画面表示は60FPSもない。たぶん。
不思議だなぁ。
矩形作る処理が長引いてsleepが短いorない→repaint()呼び出し→描画する時間もないまま次の矩形作成処理→なんとか隙をぬってorムリヤリrepaint()を進めたけど60FPS出てない みたいな感じなのか?わからん…
windowsだとこんなかんじ
GUI | 矩形の数 | repaint() | アクティブレンダリング |
AWT | 500 | 40FPS | 39FPS |
AWT | 2000 | 46FPS | 11FPS |
Swing | 500 | 40FPS | 39FPS |
Swing | 2000 | 46FPS | 10FPS |
なぜ矩形の数を増やしたのに速くなりますか?repaint()は謎だらけだぜ…
マックでBufferStrategyも使ってみた。
GUI | 矩形の数 | repaint() | アクティブレンダリング | BufferStrategy |
AWT | 500 | 60FPS | 53FPS | 41FPS |
AWT | 2000 | 60FPS | 16FPS | 13FPS |
Swing | 500 | 60FPS | 55FPS | - |
Swing | 2000 | 60FPS | 18FPS | - |
遅いじゃん…なんでよ。windowsだと?
GUI | 矩形の数 | repaint() | アクティブレンダリング | BufferStrategy |
AWT | 500 | 40FPS | 39FPS | 50FPS |
AWT | 2000 | 46FPS | 11FPS | 14FPS |
Swing | 500 | 40FPS | 39FPS | - |
Swing | 2000 | 46FPS | 10FPS | - |
こっちは速くなった…ぬぅ。
テストに使ったソース
http://homepage.mac.com/kskeil/SwingSpeedTest.java
http://homepage.mac.com/kskeil/AwtSpeedTest.java
http://homepage.mac.com/kskeil/BSSpeedTest.java
上のwindowsってのは全部VMWwareFusionで動かしてたんだけど、BootCampでうごかしてみた。
GUI | 矩形の数 | repaint() | アクティブレンダリング | BufferStrategy |
AWT | 500 | 60FPS | 28FPS | 50FPS |
AWT | 2000 | 60FPS | 7FPS | 13FPS |
Swing | 500 | 60FPS | 23FPS | - |
Swing | 2000 | 57FPS | 7FPS | - |
repaint()は高速化、アクティブレンダリングは低速化した。へぇ。よくわかんねぇ…
アクティブレンダリングで自力ダブルバッファなしにしてみる@Mac
GUI | 矩形の数 | repaint() | アクティブレンダリング(自力DB) | アクティブレンダリング(直書き) | BufferStrategy |
AWT | 500 | 60FPS | 53FPS | - | 41FPS |
AWT | 2000 | 60FPS | 16FPS | - | 13FPS |
Swing | 500 | 60FPS | 55FPS | 50 | - |
Swing | 2000 | 60FPS | 18FPS | 13 | - |
…もうぜんぜんわからん。なんで直書きの方が遅いんだ?
と言う事で、よくわからんなりにまとめ。
- 正確な画面更新が必要な場合(ゲームとか)はアクティブレンダリングでがんばってください。
- AWTとSwingはぶっちゃけどっちでもいいです。
- ダブルバッファは自力でやるのがいいと思います。
- 更新速度(FPS)があがらない時の対応は自分でやってください。
- 検証終わり。
っていうかなんでアクティブなんだろ。パッシブの逆だからか?でも同期レンダリングとかの方がネーミングとしてはわかりやすいよーな…