5

私はソフトウェアの特定のコンポーネント (他の誰かが作成したもの) を拡張するように割り当てられました。Android 用に完全に Java で書かれています (私が知っているネイティブ/c++ コンポーネントはありません)。

コードに慣れてきたら、メソッド (レンダリング クラスの描画メソッド) に出会いました。このメソッドには、オブジェクトを更新する大きなループが含まれます (その後、別のメソッドが後でオブジェクトをレンダリングします)。メソッドの作成者は、ループの前に、すべて/ほとんどのメンバー変数と配列、および他のオブジェクトのフィールドをローカル変数にキャッシュしているように見えました。コードは次のようになります。

    float[] coordArr = mCoordArr;
    float[] texCoordArr = mTexCoordArr;
    float[] cArray = mColArray;

    // ... there are further locals too, I didn't copy all here

    float[] color = mColor;
    float r = color[0];
    float g = color[1];
    float b = color[2];
    float a = color[3];

    int texw = mTexW;
    int texH = mTexH;
    Font font = mFont;
    float[] ccords = font.ccords;
    float cf = font.cf;
    float cu = font.cu;
    int len = mCurLength;

    // Update the objects
    for (int i = 0; i < len; ++i) {

        // A quite big loop body

        // ... all locals are accessed from the loop

    }

レンダリング コンポーネントはシングル スレッドであり、すべてのメンバー変数があります。

Java/Dalvik 逆アセンブラで確認したところ、バイトコード コメントには、メソッドが41のレジスタを使用していると書かれています。著者は、JIT を支援し、フィールド/配列アクセスの時間を節約するためにそれらをローカルにキャッシュしたと思いますが、これはパフォーマンスに反する多数のローカルではありませんか? たとえば、「レジスタープレッシャー」について聞いたことがあります。

必要がない場合 (つまり、現在のコードに問題がない場合) はコードを書き直したくありません。プロファイルを作成するには、コードを書き直す必要があります (それ以外の場合は、1 つのバージョンしか存在しないため、現在のコードは比べ物にならない…)。

「あまりにも」多くのローカルを使用することが推奨されない場合、超えてはならない「最適な」最大値はありますか? (もちろん、システムのスタック サイズがハード リミットであることは知っています。) その場合、ソフトウェアの他の部分も修正する必要があるかもしれません (元の作成者がすべてをローカルに入れるほど親切だった場合)。

4

1 に答える 1

6

ローカル変数が多いと「レジスタ プレッシャ」が発生する可能性がありますが、これは単に、コンパイラがより多くのメモリ フェッチを行う可能性が高いことを意味します。ただし、別の方法としては、(たとえば) 参照の置換がrありますcolour[0]。これには、理論的にはインデックス チェックと間接フェッチが含まれ、レジスタ不足に起因する可能性があるよりも多くのメモリ フェッチが発生する可能性があります

要するに、簡単な答えはありません。

したがって、特に次の場合は、コードをそのままにしておく傾向があります。

  • プロファイリングの結果、元の/前の著者が現在のデザインに到達したという証拠がある、または

  • コードはすでに十分に高速に実行されます...

于 2013-01-06T05:23:04.100 に答える