67

私は高性能のAndroidアプリケーション(ゲーム)に取り組んでおり、最初は読みやすさのためにコーディングしようとしていますが、内部で何が起こっているのかを心の奥底に留めておきたいと思っています。C ++を使用して、コンパイラーが私のために何をするか、何をしないかについて、かなり良い直感を身に付けました。私はJava/Androidでも同じことをしようとしています。

したがって、この質問。私はこのトピックについてウェブ上でほとんど見つけることができませんでした。Javaコンパイラ、Dalvikコンバータ(dx)、および/またはJITter(Android 2.2以降)は、次のような最適化を実行しますか?

  • メソッドのインライン化。どのような条件下で?privateメソッドは常に安全にインライン化できます。これは行われますか?public finalメソッドはどうですか?他のクラスのオブジェクトのメソッド?staticメソッド?オブジェクトの実行時タイプがコンパイラーによって簡単に推測できる場合はどうなりますか?final可能な限り、または可能な限りメソッドを宣言する必要がstaticありますか?

  • 一般的な部分式除去。たとえば、someObject.someField2回アクセスした場合、ルックアップは1回だけ実行されますか?ゲッターへの呼び出しの場合はどうなりますか?算術式を2回使用するとどうなりますか。一度だけ評価されますか?for値が変更されないことがわかっている式の結果をループの上限として使用するとどうなりますか?

  • 配列ルックアップの境界チェック。forツールチェーンは、典型的なループなどの特定の条件でこれを排除しますか?

  • 値のインライン化。一部へのアクセスはpublic static final int常にインライン化されますか?彼らが別のクラスにいるとしても?別のパッケージに入っていても?

  • 分岐予測。これもどれほど大きな問題ですか?ブランチングは、一般的なAndroidデバイスで大きなパフォーマンスヒットですか?

  • 単純な算術。someInt * 2に置き換えられsomeInt << 1ますか?

その他..。

4

3 に答える 3

105

JIT@Googleで働いているエンジニアの一人であるベンです。ビルと私がこのプロジェクトを開始したときの目標は、リソースの競合(メモリフットプリント、コンパイラスレッドによってハイジャックされたCPUなど)への影響を最小限に抑えて、動作するJITをできるだけ早く提供し、ローエンドデバイスで実行できるようにすることでした。良い。したがって、非常に原始的なトレースベースのモデルを使用しました。つまり、JITコンパイラに渡されるコンパイルエンティティは基本ブロックであり、1つの命令と同じくらい短い場合もあります。このようなトレースは、インタプリタとコードキャッシュのルックアップが頻繁に呼び出されないように、チェーンと呼ばれる手法によって実行時につなぎ合わされます。ある程度のスピードアップの主な原因は、頻繁に実行されるコードパスで繰り返されるインタプリタ解析のオーバーヘッドを排除することです。

そうは言っても、FroyoJITで実装されたローカル最適化はかなりあります。

  • レジスタ割り当て(JITがThumbコードを生成するためv5teターゲットの場合は8レジスタ、v7の場合は16レジスタ)
  • スケジューリング(例:Dalvikレジスターの冗長なld / st除去、ロードホイスト、ストアシンク)
  • 冗長ヌルチェックの排除(そのような冗長性が基本ブロックにある場合)。
  • 単純なカウントループのループ形成と最適化(つまり、ループ本体にサイド出口がない)。このようなループの場合、拡張帰納法変数に基づく配列アクセスが最適化され、ループプロローグでのみヌルチェックと範囲チェックが実行されます。
  • 実行時に動的パッチを適用する仮想コールサイトごとに1つのエントリインラインキャッシュ。
  • mul/divのリテラルオペランドの電力削減などのぞき穴の最適化。

ジンジャーブレッドでは、ゲッター/セッター用の単純なインライン化を追加しました。基盤となるJITフロントエンドは依然として単純なトレースベースであるため、呼び出し先にブランチがある場合、インライン化されません。ただし、インラインキャッシュメカニズムは、仮想ゲッター/セッターを問題なくインライン化できるように実装されています。

現在、コンパイルスコープを単純なトレースを超えて拡大し、コンパイラがコード分析と最適化のためのより大きなウィンドウを持つように取り組んでいます。乞うご期待。

于 2011-02-08T07:20:38.397 に答える
10

私の答えがあなたのすべての質問に答えるわけではないと確信していますが、1つでも答えればそれは勝利だと思います。

あなたはその主題について深い知識を持っているようで、あなたが何を望んでいるかを知っているので、あなたは次のことをしたいかもしれません。調査したい側面を含むサンプルアプリケーションを作成します。

取得したAPKを取得し、APKツールで実行します。自分のコードをリバースエンジニアリングして、意図したとおりに実行することは、私たちが知っているようにまったく問題ありません。

APKツールは、リソースを抽出してデコードし、.dexファイルをリバースエンジニアリングしてファイルに変換し.smaliます。ファイルの読み取り方法とその制限に関する詳細情報を取得するには、 smaliプロジェクトも検索することをお勧めします。.smali

繰り返しになりますが、これですべての質問に答えられるわけではないと確信していますが、良いスタートになるかもしれません。

于 2011-02-06T12:28:46.307 に答える
5

まず、私はdalvikの専門家ではないので、私の回答のいくつかは間違っている可能性があると言って、この前置きをさせてください。しかし、私はdalvikのJITコードを掘り下げており、dalvikが実行するバイトコードについてはよく知っています。

  1. メソッドのインライン化-私が知る限り、これは決して起こりません。バイトコードレベルでは発生しないとほぼ確信しています。現在、JITレベルでは発生しないと思いますが、将来的には発生する可能性があります。

  2. 一般的な部分式除去-これは、非最終変数/フィールドを使用しない部分式に対してのみ行われると思います。それでもそうなるとしたら、私は完全に前向きではありません。それが行われる場合、おそらくJITレベルではなく、バイトコードレベルで行われることを期待します。

  3. 配列ルックアップの境界チェック-手がかりなし

  4. 値のインライン化-私が知る限り、そうです-それらはすべてのシナリオでインライン化されます。

  5. 分岐予測-わからない

  6. 単純な算術-私が知る限りではない

また、あなたへの別のアプローチ方法についても触れておきたいと思います。dxとdalvikはどちらもオープンソースなので、好きなように掘り下げることができます。それらは明らかに小さなコードベースではないので、そのレベルでそれらを掘り下げるにはかなりの努力が必要です

于 2011-02-07T03:29:49.617 に答える