Androidパフォーマンスの最適化-メモリのディザを徹底的に解決

6985 ワード

起源
メモリジッタは,短時間で多数のオブジェクトが新生領域に出入りするため,頻繁なGCを伴う.gcはuiスレッドとcpuリソースを大量に占有し、app全体のカートンを招く.
Android profile効果図は以下の図
Memoryで
上の白いゴミ箱が見えます.gc操作を大量に実行することを説明する.しばらくすると携帯電話のカードが切れ始めました
学習内容
  • android studio 3.0コンパイラメモリジッタ
  • を表示
  • ツールを使用して、メモリのジッタを引き起こすコードを迅速に位置決めします.
  • では、どのようなエラー操作がメモリを理解し、回避する方法を学習します.

  • クイックポジショニングメモリジッタ
    高速位置決めにはddmsも使用する必要があります.莫慌asにはTools->Android->Android Device Monitorが付属しており、以下の操作を行います.
    そして私たちは以下の写真を見ます.
    慌てないで.
    真ん中の赤い枠は私たちが分析しなければならない内容で、彼がバラツキを持っているのはメモリのジッタによるものです.
    そして赤い枠の内容を拡大します.マウスをクリックして右にドラッグすると大きくなり、赤い枠の上の数字をクリックすると小さくなります.
    私たちは震える場所を拡大しました.クリックすると下図のスタイルが表示されます
    このピンクのアーチの模様が見えます.左側から右側にかけて、関数が消費する時間を表します.
    次に、問題のあるコードがどこにあるかを迅速に特定します.
    私は勝手にスライドして、勝手に1つ選んで、それから下に私が選んだ関数の方法を示しました.
    ここには細部があります
  • onClickの一番前の番号は9
  • です.
  • Parentのメソッド番号は8
  • です.
  • childrenのメソッド番号は10
  • です.
    onClickのシーケンス番号がonClick呼び出しのメソッドのシーケンス番号より大きいことを示します.onClickが呼び出されたメソッドのシーケンス番号より小さい.
    Parentの下の方法をクリックし続けると番号1の方法が見つかります
    下図のように.
    エラーコードがどこにあるか見つけました.ではソースコードの様子を見てみましょう
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    imPrettySureSortingIsFree();
    
                }
            });
        }
    
        /**
         *           ,     
         */
        public void imPrettySureSortingIsFree() {
            int dimension = 300;
            int[][] lotsOfInts = new int[dimension][dimension];
            Random randomGenerator = new Random();
            for (int i = 0; i < lotsOfInts.length; i++) {
                for (int j = 0; j < lotsOfInts[i].length; j++) {
                    lotsOfInts[i][j] = randomGenerator.nextInt();
                }
            }
    
            for (int i = 0; i < lotsOfInts.length; i++) {
                String rowAsStr = "";
                //  
                int[] sorted = getSorted(lotsOfInts[i]);
                //    
                for (int j = 0; j < lotsOfInts[i].length; j++) {
                    rowAsStr += sorted[j];
                    if (j < (lotsOfInts[i].length - 1)) {
                        rowAsStr += ", ";
                    }
                }
            }
    
    
        }
    
        public int[] getSorted(int[] input) {
            int[] clone = input.clone();
            Arrays.sort(clone);
            return clone;
        }
    
    }
    
    

    rowAsStrオブジェクトが作成され続けていることがわかりました.最適化してみましょう
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    imPrettySureSortingIsFree();
    
                }
            });
        }
    
        /**
         *           ,     
         */
        public void imPrettySureSortingIsFree() {
            int dimension = 300;
            int[][] lotsOfInts = new int[dimension][dimension];
            Random randomGenerator = new Random();
            for (int i = 0; i < lotsOfInts.length; i++) {
                for (int j = 0; j < lotsOfInts[i].length; j++) {
                    lotsOfInts[i][j] = randomGenerator.nextInt();
                }
            }
    
            //    
            StringBuilder sb = new StringBuilder();
            String rowAsStr = "";
            for(int i = 0; i < lotsOfInts.length; i++) {
                //     
                sb.delete(0,rowAsStr.length());
                //  
                int[] sorted = getSorted(lotsOfInts[i]);
                //    
                for (int j = 0; j < lotsOfInts[i].length; j++) {
    //                rowAsStr += sorted[j];
                    sb.append(sorted[j]);
                    if(j < (lotsOfInts[i].length - 1)){
    //                    rowAsStr += ", ";
                        sb.append(", ");
                    }
                }
                rowAsStr = sb.toString();
                Log.i("ricky", "Row " + i + ": " + rowAsStr);
            }
    
        }
    
        public int[] getSorted(int[] input) {
            int[] clone = input.clone();
            Arrays.sort(clone);
            return clone;
        }
    
    }
    
    

    これでメモリがブレません
    問題を見つけることができて、この問題は基本的に解決しました.
    次に、メモリのジッタを回避するためのいくつかの推奨事項を示します.
  • は、ループ内でオブジェクトを作成することをできるだけ避け、オブジェクトの作成をループ外に移動する必要があります.
  • ビューをカスタマイズするonDraw()メソッドは頻繁に呼び出されるので、ここで頻繁にオブジェクトを作成するべきではありません.
  • Bitmapを大量に使用する必要がある場合は、配列にキャッシュして多重化してみましょう.
  • は、多重化可能なオブジェクトについても、オブジェクトプールを使用してキャッシュすることができる.

  • その他
    分析パネルの列名は次のとおりです.
    Name
    パッケージ名とパラメータ情報を含むメソッドの詳細
    col 3 is
    right-aligned
    col 2 is
    centered
    zebra stripes
    are neat
    Incl Cpu Time
    Cpuがこのメソッドとそのサブメソッドを実行するのにかかる時間
    Incl Cpu Time %
    Cpuこのメソッドを実行するこのメソッドとそのサブメソッドにかかるCpuの合計実行時間の割合
    Excl Cpu Time
    Cpuがこの方法を実行するための通話料の時間
    Excl Cpu Time %
    Cpuがこの方法を実行する通話料の時間がCpuの総時間に占める割合
    Incl Real Time
    このメソッドとそのサブメソッドは、通話料の実際の時間を実行し、このメソッドを実行してから終了するまでにどれだけの時間がかかりましたか.
    Incl Real Time %
    合計実行時間に対する上記時間の割合
    Excl Real Time %
    このメソッド自体の実際の許容時間
    Excl Real Time
    合計許容時間に対する上記時間の割合
    Calls+Recur
    呼び出し回数+再帰回数はメソッドにのみ表示され、子展開後の親メソッドと子メソッドの欄は次のデータに置き換えられます.
    Calls/Total
    呼び出し回数と合計回数の割合
    Cpu Time/Call
    Cpu実行時間と呼び出し回数の割合は、この関数がcpuを消費する平均時間を表します.
    Real Time/Call
    実際の時間の呼び出し回数に対する割合.この表の関数の平均実行時間
    リファレンス
    https://www.youtube.com/watch?v=McAvq5SkeTk