Androidアプリの描画パフォーマンスを向上させる方法 第1回

ウェブテクノロジ開発部の西田です。

今回は、Androidアプリケーションを開発されている方々に向けて、Androidアプリケーションの描画パフォーマンスを向上させる方法についてご紹介いたします。

スマートフォンアプリケーションを作り始めたものの、後々になって期待していたパフォーマンスが得られず苦労した、という経験はありませんでしょうか?
どうすれば快適でより良いパフォーマンスのアプリケーションが作れるのか?そういった悩みを今回の記事で少しでも解消してもらえると幸いです。

本テーマは数回に分けて紹介する予定ですが、第1回となる今回は、描画方法による描画パフォーマンスの違いについてご紹介いたします。

作り方次第で描画パフォーマンスが何倍も変わる!

Androidアプリケーションで画像を描画する方法はいくつもあり、もちろんそれぞれで描画パフォーマンスが異なります。
Androidで最も標準的な描画方法であるViewで描画した場合と、OpenGL ESを利用した場合で、描画パフォーマンスにどれくらいの違いが出るのかを見てみましょう。

fps View vs OpenGL
画像フォーマット PNG-32 (透過あり)
画像サイズ 64 x 64 pixel
画像枚数 500, 1000
測定方法 移動 (回転、拡大縮小なし)
端末 Galaxy S2 (Android2.3)

この計測結果から、OpenGL ESで描画した場合では、Viewで描画した場合に比べ、描画パフォーマンスが約260%も向上することがわかります。

ただ、「こんなに早いからいつもこの方法で作ればいいのだ!」というわけではなく、描画パフォーマンスが良いからといって、あなたのAndroidアプリケーションにとってそれが必ずしも最も良い方法になるわけではありません。

測定の条件(画像サイズや枚数、機種など)によっては、必ずしも今回と同様のパフォーマンスが得られるわけではなく、OpenGL ESを使用した場合はコードがやや複雑になるため、生産性やソフトウェアの品質が低下する可能性もあります。
また、早ければ早いほど電力消費が激しくなるという問題もあります。

では、あなたとって最も良い方法とは何なのでしょうか?

fpsとは?

Frame Per Secondの略で1秒あたり何枚のフレームが処理されるかを示す単位です。

Android端末ではディスプレイのフレームレートを制限していることが多く、GalaxyS2では60fpsが最大でした。(アナログテレビのNTSC方式では60fps(厳密にはインターレース走査で30fps×2)で規定されており、液晶パネルのVSYNCも主に60fps(60Hz)で動作します。)

fpsが低いと動きがカクカクしてしまい操作感が悪くなりますが、常に60fpsが必要というわけではありません。ものすごく激しいアクションゲームでもなければ、安定的に30fps程度が出せれば大丈夫です。

まずはAndroidのおさらいから

描画パフォーマンスだけに限らず、アプリケーションを作る上では開発言語やそのプラットフォームの仕組みを理解することが重要です。
まずはAndroidの仕組みについて触りだけでもおさらいしておきましょう。

言うまでもありませんが、Androidとはスマートフォンやタブレットなどを主なターゲットとしてGoogleによって開発されたプラットフォームです。2012年7月現在、Android 4.0 (Ice Cream Sandwich) がリリースされています。

Android architecture

 AndroidのフレームワークとアプリケーションはJava言語で作成され、Google独自の仮想マシンであるDalvik VM上で動作します。そのため、Androidアプリケーションは基本的にはJava言語で開発することになります。(C/C++での開発もサポートされていますが、それはまた別の機会にでも)

Dalvik VMは少ないメモリでも動作できるように最適化されており、一部のAPIが省かれたり追加されたりと、通常のJava VMとはやや動作が異なっています。(Sun Javaの互換性テストも通過していないそうです。)そのため、Javaだけれども今までと全く同じJavaなわけではない、ということを意識しておく必要があります。

描画方法によるパフォーマンスの違い

Androidアプリケーションで利用できる描画方法にはどのようなものがあるのでしょうか?
主に用いられる描画方法について説明します。

View

Androidアプリケーションを作る上でもっとも標準的な描画方法で、Canvasとよばれる領域に描画し表示します。

この描画方法では、描画以外の処理と同じアプリケーションスレッドで描画されるため、描画以外の処理の影響を受けやすく描画速度が遅くなりがちです。

SurfaceView

Canvasに描画するところは通常のViewと同じですが、通常のViewとは異なり、アプリケーションスレッドではない別のスレッドで描画します。

そのため、描画以外の処理の影響をあまり受けず、Viewよりも高いパフォーマンスで描画することが可能です。

OpenGL ES (VBO Extension)

AndroidプラットフォームにはOpenGL ESが搭載されており、Androidアプリケーションから利用することができます。

OpenGLの一般的な描画方法では、頂点データをJava側で保持し描画ごとにGPU側のメモリに転送し描画させます。ただ、この方法では描画のたびにメモリ転送が発生するため速度が低下します。

そこで、この描画方法ではVertex Buffer Object (VBO) を使い、描画させる前にあらかじめ頂点データをGPU側のメモリに転送しておくことによって、余分な転送を減らし高速な描画を実現します。

OpenGL ES (Draw Texture Extension)

Draw Texture Extensionは、通常の3Dを想定した作りではなく、2Dを前提として処理を極力省くことにより高速に描画させる方法です。

ソースコード的には glDrawTexfOES() を使い、平面にテクスチャを張り付けます。ただし、この方法では画像の回転ができないという制約があります。

では、描画方法でどれくらい描画パフォーマンスに違いが出るのか、実際の計測値を見てみましょう。

fps 32x32
画像フォーマット PNG-32 (透過あり)
画像サイズ 32 x 32 pixel
画像枚数 100~1000 (100きざみ)
測定方法 移動 (回転、拡大縮小なし)
端末 Galaxy S2 (Android2.3)

32x32pixelの画像を使った場合では、ある程度の枚数まではどの描画方法でも描画速度にあまり差はでず十分なパフォーマンスが得られています。また、ある程度の枚数を超えると徐々に描画速度が低下していきますが、どの描画方法でも描画速度に大きな差は出てきません。

ところが256x256pixelの画像を使った場合では、明らかな差が見えてきます。

fps 256x256
画像フォーマット PNG-32 (透過あり)
画像サイズ 256 x 256 pixel
画像枚数 100~1000 (100きざみ)
測定方法 移動 (回転、拡大縮小なし)
端末 Galaxy S2 (Android2.3)

高負荷になるとViewでは顕著に描画速度が低下し、少ない枚数でも実用に耐えられるパフォーマンスが得られません。SurfaceViewに関してもViewよりはましではあるものの同様の傾向が見られます。

OpenGL ES (VBO Extension)、OpenGL ES (Draw Texture Extension)でも負荷がかかれば掛かるほど描画速度の低下が見られますが、ViewやSurfaceViewに比べるとある程度までは十分な描画パフォーマンスが得られています。

ただし、OpenGL ES (Draw Texture Extension)以外では、画像枚数が増えていくと描画ができなくなってしまっています。

※描画できない理由はOutOfMemory(メモリ不足)が主な原因です。なお、測定では画像やテクスチャを使い回さず、すべての画像に対してメモリを確保しています。

やや大きなまとめ方ですが、小さい画像を扱う分には、どの描画方法をとってもあまり描画パフォーマンスに差はでず、大きい画像を扱うときは、OpenGL ESを利用した描画方法を選択した方が良いことが多いと考えられます。

目的に応じて描画方法の選択を

画像をあまり使用せずアニメーションもさせない場合は、描画パフォーマンスを追求する必要はありませんので、Viewを使った描画で十分です。

画像を大量に使用する場合やアニメーションさせるような場合では、OpenGL ESを使用すると、高い描画パフォーマンスが得られます。ただし、ある程度の負荷まではOpenGL ESを使わずとも十分な描画パフォーマンスを得られます。

先に述べたように、OpenGL ESを使用した場合はコードがやや複雑になるため、生産性や品質を重視する開発の場合では、SurfaceViewでの描画を選択した方がトータル的には良い、ということもあります。

一番大切なことは、使う画像のサイズや枚数、アプリケーションの目的などを事前に確認し、適切な描画方法を選択することです。

次回は

次回は、画像の違いによるパフォーマンスの違いについてご紹介いたします。

画像の種類によって速度って変わるの?サイズや枚数は?透過は?といった疑問について考察し、あなたのAndroidアプリケーションに最も適切な画像を見つけるための情報を公開いたします。

タグ , , | 2020/06/16 更新 |