Baidu アプリのスタートアップ パフォーマンス最適化の実践

ここに画像の説明を挿入

I.はじめに

起動パフォーマンスは、Baidu アプリの中核指標の 1 つです。ユーザーは、アプリの応答性と読み込みの速さを期待しています。起動に時間がかかりすぎるアプリは、この期待を満たしておらず、ユーザーを失望させる可能性があります。この劣悪なエクスペリエンスにより、ユーザーはアプリ ストアでアプリに低い評価を与えたり、アプリを放棄したりする可能性があります。あなたのアプリを完全に。起動パフォーマンスの最適化はエクスペリエンス最適化の最も重要な部分となっており、Baidu App はこの方向への投資を継続し、継続的に最適化してユーザー エクスペリエンスを向上させます。

起動時のパフォーマンスの最適化は、概要、ツール、最適化、劣化対策に分けて、主にパフォーマンスの最適化に関する内容を説明します。

Baidu App ローエンド マシンの最適化 - 起動パフォーマンスの最適化 (概要)

Baidu アプリ Android 起動パフォーマンス最適化ツール

Baidu アプリのパフォーマンス最適化ツール - Thor の原則と実践

2. 最適化理論

起動パフォーマンス最適化の認識によって、起動パフォーマンス最適化の方向性と考え方が決まり、ひいては最適化の効果が決まります。多くの開発者は、Google 開発者向けドキュメントの起動プロセスの説明から起動プロセスを理解しています。

写真

1. アプリケーションオブジェクトを作成します。

2. メインスレッドを開始します。

3. メインアクティビティを作成します。

4. 拡張ビュー。

5. レイアウト画面。

6. 初期描画を実行します。

アプリケーション プロセスが初めて描画を完了すると、システム プロセスは現在表示されている背景ウィンドウをメイン アクティビティに置き換えます。この時点で、ユーザーはアプリの使用を開始できます。

上記では主にアプリケーションの起動プロセスの各段階を紹介しましたが、これは概要に過ぎず、実際には多くの起動方法があり、起動パスごとに実行されるロジックが異なる可能性が非常に高いです。パス全体のうちの 1 つは最適化プロセスにあり、次の図に示すように、非常に重要な役割を果たします。

写真

起動プロセスでは、デスクトップ アイコンをクリックするコールド スタート方法が主流ですが、プッシュ スタート、ブラウザ起動などのオフデバイス変換による起動方法も比較的一般的です。基本的に、プロセスの作成、フレームの読み込み、ホームページのレンダリング、および 4 つのリンクのプリロードに分解できます。起動パフォーマンスの最適化では、主にデスクトップ アイコンをクリックするパスだけでなく、エクスペリエンスの究極の最適化を達成するための起動パス全体の最適化にも取り組みます。

最適化ポイントを見つけ出し、最適化の限界を探るために、起動プロセスをシステム レベルで理解する必要もあります。起動プロセスは非常に複雑で、ユーザーが通常使用するページの表示を完了するには、多くのシステム レベルのプロセスの連携が必要です。次の図は、アイコンをクリックする起動プロセスを示しています。

写真

起動プロセスは次のように大まかに要約できます。

1. ランチャーは、APP のメイン アクティビティを開始するように AMS に通知します。

2. ActivityManagerService (以下、AMS) は、開始されるアクティビティ情報を記録し、Launcher に一時停止状態に入るように通知します。

3. ランチャーが一時停止状態に入ると、一時停止されたことを AMS に通知し、アプリの起動を開始します。

4. アプリは開かれておらず、AMS は新しいプロセスを開始し、新しいプロセス内で ActivityThread オブジェクトを作成し、その中で main 関数メソッドを実行します。

5. アプリのメインスレッドが開始された後、AMS に通知し、通信のためにそれを applicationThread に渡します。

6. AMS は、アプリケーションをバインドして MainActivity を開始するようにアプリケーションに通知します。

7. MainActivitiy を開始し、Context を作成して関連付け、最後に onCreate メソッドを呼び出して、最終的にページの描画と画面のアップロードを完了します。

メインプロセスの機能は主に次のとおりです。

1. ランチャー プロセス: 携帯電話のデスクトップ プロセスであり、ユーザーのクリック イベントを受信し、そのイベントを AMS に通知する役割を果たします。

2. SystemServer プロセス: アプリケーションの起動プロセスのスケジューリング、プロセスの作成と管理、ウィンドウの作成と管理 (StartingWindow と AppWindow) などを担当します。コア サービスは AMS と WMS (WindowManagerService) です。

3. Zygote プロセス: フォークを通じてアプリケーション プロセスを作成します。Zygote プロセスは、初期化時に仮想マシンを作成し、必要なシステム クラス ライブラリとリソース ファイルを同時にメモリにロードします。Zygote が子プロセスをフォークした後、子プロセスは基本リソースがロードされた仮想マシンも取得するため、アプリケーション プロセスの起動が高速化されます。

4. SurfaceFlinger プロセス: 主に、Vsync 信号処理、ウィンドウ合成処理、フレーム バッファ管理などのアプリケーション レンダリングに関連します。

全体的な認識とビジョンがあれば、より高い視点に立って、携帯電話の負荷やシステムリソースの使用量の合理性など、パフォーマンスのボトルネックをより深く考えて分析し、起動パフォーマンスの最適化方法をより検討することができます。総合的に、起動パフォーマンスの究極の最適化を達成します。

3. 着陸を最適化する

Baidu アプリの起動パフォーマンスの最適化は、一般的な最適化、基本メカニズムの最適化、基盤技術の最適化の 3 つの部分に大別されます。

3.1 一般的な最適化

ビジネス開発の初期段階にあり、ビジネスの反復が比較的速い場合、この時点での最適化は比較的簡単で、最適化効果により起動速度が 1 秒以内に向上する可能性が非常に高くなります。短い期間。起動パフォーマンスの最適化も、コールド スタートアップの理解と、迅速な最適化の目標を達成するための起動タスクの整理に基づいています。前述の Trace ツールや Thor Hook ツールなどのパフォーマンス ツールを使用して、時間のかかる問題を見つけ、遅延、非同期、削除などを通じて最適化できるかどうかを評価し、入出力に基づいて作業の優先順位を評価できます。迅速な最適化を達成するための条件、パフォーマンスを開始する目的。

写真

スタートアップシーンでの徐々にビジネスが拡大するにつれて、Handbai は最も多くのビジネスを運ぶ空母レベルのモバイルアプリケーションに徐々に成長し、膨大な量を抱えていますが、巨大なビジネスの事前負荷を完全に削除したり、非同期で解決したりすることは不可能です. この部分は起動パフォーマンスの最適化のプロセスにあります. 私たちが直面している大きな問題には、バッチでのビジネスのプリロードの問題を解決するメカニズムが必要です. したがって、基本メカニズムのスケジューリング メカニズムは、プリロード要件に対処するために徐々に導出されます。スタートアッププロセス中のさまざまなビジネス。

3.2 基本メカニズムの最適化

基本メカニズムの最適化は、主にスケジューリング メカニズムの最適化と基本コンポーネントのパフォーマンスの最適化に分けられます。

3.2.1 タスクのスケジューリングの最適化

多くのビジネスが存在し、プリロード タスクの実行要件は異なります。起動パフォーマンスとビジネス プリロードのバランスをとるために、Baidu App はタスク スケジューリング フレームワークを構築し、ビジネス パーティがアクセスを通じてパフォーマンスの問題を迅速に最適化できるようにする必要があります。

写真

タスク スケジューリングの全体的な構造は次のとおりで、現在も急速に反復されています。

写真

インテリジェント スケジューリングでは、タスクの入力と情報の入力に応じて、次のようなさまざまなスケジューリング応答を行うことができます。

1. パーソナライズされたスケジューリング戦略: ビジネスのプリロードタスク ID がユーザーの行動習慣と一致すると識別された場合、タスクは事前に初期化され、タスクの優先度が向上し、同時にユーザーが対応するページにアクセスしたときにタスクが優先されます。ビジネスに関連しないタスクは回避する必要があります。

2. 階層的エクスペリエンス戦略: 指定されたモデル構成に対応するスケジューリング戦略があることが特定された場合、即時スケジューリング、遅延スケジューリング、スケジューリングなしなど、主に使用される対応するスケジューリング機能が実行されます。劣化を経験する。

3. 洗練されたスケジューリング戦略: さまざまなシナリオでビジネスのプリロード タスクを細かくスケジュールします。たとえば、スプラッシュ スクリーンのシナリオでは、スプラッシュ スクリーンに関連するビジネス情報を識別し、プリロードを実行します。シーンが端末の外部で呼び出されたときに、ランディング ページのビジネス情報を特定し、対応するプリロードを実行します。

4. 優先度に基づく遅延スケジューリング: 遅延スケジューリングに依存するタスクの初期化が多数あり、業務の初期化を秩序正しく制御する必要があるため、遅延スケジューリングに優先度の概念を追加することで、遅延スケジューリングにも優先順位を付けることができます。スケジューリング: 優先度の高いタスクをより速く実行できるようにします。

5. ホームページ UI 並列レンダリング スケジューリング: 主にコールド スタート フェーズで商用スプラッシュ スクリーン ビジネスを提供します。商用スプラッシュ スクリーンを表示する必要があるかどうか、およびどのマテリアルを表示するかは、コールド スタート フェーズでのリアルタイム ネットワーク リクエストによって決定されます。 . コールド スタート フェーズ中に商用ネットワークをできる限り改善する必要があります。リクエストの利用可能時間は、それによってネットワーク リクエストの成功率を向上させます。現在、Baidu アプリで確認できます。最初にホームページを初期化できます。ホームページレンダリングサービスを送信すると、商用ネットワークに提供できるように、商用スプラッシュスクリーンが表示されるかどうかがチェックされます ホームページの初期化を妨げずに、より多くの利用可能時間をリクエストしますこの技術により商用ネットワークリクエストの成功率が大幅に向上し、商用収入の増加をもたらします。

スケジューラー フレームワークには多くの詳細が含まれるため、ここではスケジューラーの 1 つである階層エクスペリエンス スケジューラーの設計について簡単に紹介します。

写真

これは主に、モデル評価、階層構成、階層スケジューリング メカニズムの 3 つのモジュールに分かれており、さまざまな構成の携帯電話で最適なエクスペリエンスを実現します。

  • モデルの評価:

  • 静的スコアリングと呼ばれる、デバイス情報を通じてスコアリング情報を計算します。

  • 動的スコアリングと呼ばれる、パフォーマンス指標を通じてスコア情報を計算します。

  • モデル トレーニング スコアリング情報に従って、最終的なモデル スコアが取得されます。

  • グレーディング構成:

  • クラウド構成テーブル: 機器の評価条件に応じてサービスレベルごとに段階的な構成テーブルを提供し、動的更新と増分更新をサポートし、更新はバックエンドでタイムリーに反映されます。

  • ローカル プリセット テーブル: 構成テーブルは、最初のインストール時にローカルにプリセットされます。

  • モデルの評価情報と分類構成情報に基づいて、制御戦略が取得されます。

  • 階層型スケジューリング:

  • ビジネス側は、モデルの評価に基づいてさまざまなビジネス ロジックを制御し、ハイエンド電話機のすべての機能の最適なエクスペリエンス、ミッドレンジ電話機の一部の機能の優れたエクスペリエンス、およびローエンド電話機のコア機能のスムーズなエクスペリエンスを実現します。ターミナル マシンでは遅延読み込み戦略を使用し、ローエンド マシンではオフ状態を選択します。

3.2.2 KV ストレージの最適化

SharedPreferences は、Android プラットフォーム上の軽量のストレージ クラスです。アプリケーションの構成情報を保存するために使用されます。その本質は、データの XML ファイルを「キーと値」ペアの形式で保存することです。ファイルは次の場所に保存されます。 /data/data/pkg/shared_prefs ディレクトリには、キーと値のペアの形式で保存されるという利点があり、使いやすく理解しやすいですが、読み取りと書き込みのパフォーマンスが遅いなど、SharedPreferences の欠点は明らかです。 , IOの読み取りと書き込みはxmlデータ形式を使用しており、完全な更新の効率が低い、マルチプロセスのサポートが不十分、保存されたデータが失われやすい、多くのスレッドが作成されるため、パフォーマンスが低下します。

読み取りパフォーマンスが低い

SP ファイルが読み込まれるたびにサブスレッドが作成されます。ソースコードは次のとおりです。

private final Object mLock = new Object();
private boolean mLoaded = false;
private void startLoadFromDisk() {
    synchronized (mLock) {
        mLoaded = false;
    }
    new Thread("SharedPreferencesImpl-load") {
        public void run() {
            loadFromDisk();
        }
    }.start();
}

ただし、キーと値の取得時にロードが完了していない場合は、SP ファイルがロードされるまで待機します。

public String getString(String key, @Nullable String defValue) {    synchronized (mLock) {        awaitLoadedLocked();        String v = (String)mMap.get(key);        return v != null ? v : defValue;    }}

書き込みパフォーマンスが悪い

SP は XML 形式を採用しており、書き込みごとに完全な更新が行われるため非効率です。書き込み方法は 2 つあります。

  • commit: 現在のスレッド モードをブロックします。変更がメモリに送信された後、IO が完了するまで待ちます。メイン スレッドがコミット モードを使用している場合、スタックする可能性が非常に高くなります。

  • apply: は現在のスレッドをブロックしませんが、メイン スレッドがフリーズする可能性がある隠れた穴があります。主な理由は、apply メソッドが書き込み Runnable を QueueWork に追加することです。コンポーネントが回転されると、QueueWork が完了したかどうかを確認し、完了していない場合は待機します。コードは次のとおりです。

  public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,        int configChanges, PendingTransactionActions pendingActions, String reason) {        ......        // 确保写任务都已经完成        QueuedWork.waitToFinish();        ......    }}

したがって、ANR/スタック監視では、多くの SharedPreferences スタックが確認できます。スタックはシステム レベルのスタックであるように見えますが、実際には SP apply メソッドによって導入された問題です。スタックは次のとおりです。

java.lang.Object.wait(Native Method) 
java.lang.Thread.parkFor$(Thread.java: ) 
sun.misc.Unsafe.park(Unsafe.java: )
java.util.concurrent.locks.LockSupport.park(LockSupport.java: ) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java: ) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java: )
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java: ) 
java.util.concurrent.CountDownLatch.await(CountDownLatch.java: ) 
android.app.SharedPreferencesImpl$EditorImpl$1.run(SharedPreferencesImpl.java: ) 
android.app.QueuedWork.waitToFinish(QueuedWork.java: ) 
android.app.ActivityThread.handleServiceArgs(ActivityThread.java: )
android.app.ActivityThread. - wrap21(ActivityThread.java) 
android.app.ActivityThread$H.handleMessage(ActivityThread.java: ) 
android.os.Handler.dispatchMessage(Handler.java: ) 
ndroid.os.Looper.loop(Looper.java: ) 
ndroid.app.ActivityThread.main(ActivityThread.java: )
java.lang.reflect.Method.invoke(Native Method) 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: ) 
com.android.internal.os.ZygoteInit.main(ZygoteInit.java: )

マルチプロセスのサポートが不十分

MODE_MULTI_PROCESS フィールドを使用する場合、Android には複数のプロセスによる競合を防ぐ適切なメカニズムがないため、実際には信頼性が低く、アプリケーションはこれを使用すべきではなく、ContentProvider を使用することをお勧めします。上記の説明から、{MODE_MULTI_PROCESS} で識別される SharedPreferences に複数のプロセスがアクセスすると、競合が発生することがわかります。たとえば、プロセス A ではキーが明確に設定されており、それを取得するためにプロセス B にジャンプしますが、プロンプトが表示されます。ヌルい間違い。

写真

3.2.2.1 最適化スキームの設計

現在、大手メーカーもある程度の SP の最適化を行っており、主に書き込みによる ANR 問題を解決するために、現在の SP の仕組みに基づいて最適化された保守的な最適化と、破壊的な最適化、より代表的な最適化があります。 1 つは MMKV と Data Store ですが、評価後に特定の問題が発生する可能性があるため、Baidu アプリの最適化では、業界の主流の処理方法からも学び、最終的に 2 つの最適化方法を採用しました。

  • 破壊的な最適化コンポーネントを提供します。ネイティブ SP の一連の問題を完全に解決する UniKV、コア シーンには究極のエクスペリエンスがあり、ビジネス側は積極的に接続します。

  • システム SP メカニズムを最適化して、書き込み時の AN​​R などの問題点を解決し、主に UniKV に接続されていない SP ファイルを提供します。

3.2.2.1.1 UniKV 設計

階層設計

写真

1: ビジネスでの使用は UniKV に直接依存しており、UniKV は SharedPreferences を継承し、ネイティブ SP インターフェイスと連携します。

2: プロジェクトにはネイティブ実装と UniKV 実装が含まれており、コードはネイティブ実装に直接依存しており、ビジネス プラットフォームの出力機能を確保するためにコンパイルおよびパッケージ化するときにネイティブ実装を UniKV 実装に置き換えます。

ファイルストレージフォーマットの設計

分割されたファイルヘッダー、データブロック。ファイルの最初の 40 バイトには、主にバージョン番号、ライトバック時間、予約フィールド、ディザスタ リカバリ データ長、ディザスタ リカバリ CRC、実際のデータ長、および実際の CRC が格納されます。

写真

1: スペースは 4KB 単位で割り当てられ、占有される最小スペースは 4KB です。ファイルは mmap を介してマップされ、オペレーティング システムがファイルへのデータの書き込みを担当します。

2: データ回復は、ディザスタ リカバリ データ長とディザスタ リカバリ CRC を通じて実行できます。

3: SP からの移行が成功したかどうかなど、予約フィールドを通じて機能拡張を行うことができます。

写真

データ本体はデータブロックに格納され、追記形式で書き込まれ、必要に応じてデータが整理されます

1: タイプのストレージをサポートし、SP ネイティブの getAll インターフェイスと連携します。

2: サポートされる型は次のとおりです: BOOL、INT、FLOAT、DOUBLE、SHORT、LONG、STRING、STRING_ARRAY、BYTE_ARRAY9 型。ネイティブ SP 実装と比較して、より多くの型をサポートします。

データ移行

データ移行プロセスでは、最初に SP コンテンツを読み取り、次に KV ファイルを書き込む必要があります。これには長い時間がかかります。KV ファイルは書き込みが完了した後にのみ使用可能になります。これはオンラインに隠れた危険を引き起こすため、解決する必要があります。

写真

UniKVでのデータ移行は業務に影響を与えない方式を採用しており、移行が完了していればKVファイルをそのまま使用し、移行が完了していない場合はSPファイルを継続して使用し、データ移行Runnableを実行します。スレッドプールに送信されます。データ移行中の SP ファイルの変更によるデータ損失を回避するために、SP ファイルの変更のデータ監視を登録します。移行完了フラグは予約フィールドに格納されます。通常、データ移行時には、移行が完了したかどうかのフラグを保存するためのフラグが必要となり、それを保存するには他のファイルをインポートする必要があります。ここでは予約フィールドとします。 UniKV では、この問題が非常にうまく解決されます。

マルチプロセスの実装

mmap メカニズム + カスタム ファイル ロックを使用してプロセス間のデータ同期を実現し、mmap ファイルを各プロセスのメモリ空間に、カスタム ファイル ロックは主に再帰的ロックとロック アップグレードを実現し、読み取り時のマルチプロセス共有ロック、マルチプロセス書き込みの排他的ロックを実現します。ネイティブ ファイル ロックは再帰的ロックをサポートしていません。アップグレードやアップグレードではデッドロックが発生したり、ロックが完全に解放されたりする傾向があります。そのため、カスタム ファイル ロックはプロセス間のデータ同期を実装します。マルチプロセスの実装に関しては、MMKVのマルチプロセス実装ロジックを中心に学びましたので、興味のある方はhttps://github.com/Tencent/MMKV/wiki/android_ipcを参照してください。

効果を達成する

ネイティブ SP のパフォーマンス問題を完全に解決し、読み取りおよび書き込みのパフォーマンスを大幅に向上させ、マルチプロセスの読み取りおよび書き込みをサポートし、スレッドの作成を削減し、全体的なパフォーマンス指標とビジネス指標が大幅に最適化されました。

写真

3.2.2.1.2 システム SP メカニズムの最適化

一部の SP はプラグインやサードパーティの SDK で使用されているため、UniKV を統合最適化に使用することはできず、ネイティブ SP メカニズムを最適化するソリューションを提供する必要があります。

最適化:

写真

現時点では、Baidu アプリは Android 12 で最適化されていません。主な理由は、Android 12 の実装方法が変更され、プロキシ方法が比較的複雑でコストが比較的高く、SP によって引き起こされる ANR の問題が少ないことです。 , そのため、まだ最適化されていません。

最適化効果:

このソリューションは全体的な状況を最適化し、ANR 指標の大幅な低下に加えて、DAU と維持率もプラスになりました。最適化後にデータの書き込みに影響が出るのではないかと心配する学生もいるかもしれませんが、モニタリングを通じてSP書き込みの適時性はそれほど変化はありませんが、書き込み成功率はプラスであり、ローエンドマシンでは大幅に改善されていることが分かりました。 SP の最適化により ANR が減少し、より多くのタスクが実行され、書き込み成功率が増加することを示しています。

3.2.3 ロックの最適化

性能最適化においてマルチスレッドのパフォーマンスチューニングは避けられないテーマですが、スレッドの同期を実現するために同期ロック機構(同期同期ロック、ロック同期ロックなど)が追加されますが、同期ロックの誕生により操作のアトミック性は確保されます。スレッドの安全性は向上しましたが、(ロックなしの場合と比較して)プログラムのパフォーマンスが低下しました。したがって、ここで行う必要があることの 1 つは「ロックの最適化」です。つまり、ロック機能の実現 (つまり、マルチスレッド操作の安全性の確保) とプログラムのパフォーマンスの向上 (つまり、セキュリティのためにプログラムの効率があまり失われないようにするためです))。

一般的なロック最適化方法:

写真

以下は、ロック最適化における Baidu アプリの実際の最適化実装を紹介する最適化項目です。

プロジェクトの初期段階では、Trace ツールの分析により、「モニター競合 XXX」が多数あることが判明しました。この情報の一部は、Android ART 仮想マシンが出力するロック関連の情報であり、ロックを保持しているスレッド、メソッド、ロックを待機しているスレッドなどが含まれます。ロック メソッド。具体的には以下の図のようになります。

写真

分析の結果、この問題は主に、基本コンポーネントの AB の初期化中に synchronized キーワードが誤って使用されたことが原因であり、AB のパフォーマンスを最適化し、必要に応じてアーキテクチャをアップグレードする必要があります。分析の結果、AB 基本コンポーネントにはマルチスレッドとファイル IO パフォーマンスにパフォーマンスの問題があることが判明したため、AB 基本コンポーネントはリファクタリングおよびアップグレードされ、パフォーマンスの問題が完全に解決されました。

写真

最適化後、ロックなしで読み取りと書き込みが実装されるため、ビジネス用途の ABTest コンポーネントのロック同期の問題が完全に解決されます。新旧の AB データと互換性があり、実験用スイッチと実験用 SID データをキャッシュし、JSON/PB データ形式で保存します。 . 最初の読み取りパフォーマンスは 118ms、最適化 95% (Xiaomi 5 マシン)。

3.2.4 その他の基本機構の最適化

Baidu アプリの起動パフォーマンスの最適化では、スレッドの最適化、IO の最適化、SO の最適化、メインスレッドの優先順位の最適化、ContentProvider の最適化、クラス/イメージのプリロードの最適化、イメージのプリロードなど、基本的なメカニズムに関連する多くの最適化が実行されています。 -アップロードGPUの最適化など。

スレッドの最適化

フック機能を通じてプラグインを作成し、スレッドの使用における不規則性を検出し、次のようなスレッドの使用仕様を策定します。

1: 企業内でプライベートにスレッド優先度を設定することは禁止されています。

2: ビジネスごとのスレッド プールを避けるために、統合されたスレッド プールを提供します。

3: スレッド プール/タスク スケジューラのスケジューリングが優先され、ビジネスではスレッド/スレッド プールのみの作成が禁止されています。

4: スレッド プールはスレッドの頻繁な作成を避け、パラメータを標準化する必要があります。

I/Oの最適化

フック機能を使用してプラグインを作成し、主に次のような不当な IO 問題を検出します。

  1. メインスレッドの読み書き時間が 100ms を超えています。メインスレッドの読み書き時間が長すぎると、メインスレッドの実行時間が長くなり、深刻な場合には ANR の問題が発生する可能性があります。

  2. 読み取りおよび書き込みバッファーが小さすぎます。バッファーが小さすぎると、システム コールとメモリ コピーが多すぎ、読み取り/書き込み回数が多すぎて、パフォーマンスに影響します。

SOの最適化

フック機能を通じてプラグインを作成し、SO ロードの問題を発見し、不必要な SO ロード プロセスを最適化し、非同期スレッド アドバンス戦略を通じて必要なロードを解決して、パフォーマンスを最適化するという目的を達成します。

バインダーの最適化

フック機能を通じてプラグインを作成し、バインダー通信に関連する問題を検出し、不要なバインダー通信を最適化し、必要に応じてメモリ キャッシュやファイルの永続化などを通じてパフォーマンスを最適化します。

メインスレッドの優先順位

メインスレッドの優先度は、システムがメインスレッドに割り当てるリソースを決定するもので、スレッドの優先度に問題があり、低い優先度に変更されると、CPU タイムスライスが取得できなくなる可能性が高く、走りは遅くなるでしょう。メインスレッドの優先度に関するトラブルシューティングにおいて、最も代表的なものは、業務が当該サブスレッドの優先度を設定する際に、誤って優先度を設定してしまう場合であり、以下のような場合に問題が発生します。

Thread t = new Thread();t.start();t.setPriority(3);

Android の奇妙な罠 - WeChat カートンの悲劇によって引き起こされたスレッド優先度の設定:

https://mp.weixin.qq.com/s/oLz_F7zhUN6-b-KaI8CMRw

Baidu アプリが優先度設定をチェックするとき、ネイティブ ライブラリにはスレッドの優先度を変更するロジックもあり、これも積極的に修正する必要があります。たとえば、Facebook 反応ライブラリのロジックの一部です。

写真

ContentProvider/FileProviderの最適化

Application.attachbaseContext と Application.onCreate の間で、installContentProviders メソッドが実行されます。このメソッドでは、AndroidManifest で宣言されている ContentProvider/FileProvider が実行されます。一般的に時間がかかるのは FileProvider です。主な理由は、FileProvider に IO があるためです。初期化中の操作。主な最適化は、ContentProvder/FileProvider を削除し、android:process 属性を通じて制御するか、遅延読み込みを通じてプロセス内で初期化することです。

画像の prepareToDraw の最適化

写真

トレース ツールでは、RenderThread で syncFrameState が実行されるときに、XXX テクスチャのアップロードに関連して時間がかかる問題が発生します。まず、トレースに表示される画像の幅と高さをチェックして、画像のサイズが大幅に大きくなっていないことを確認します。表示される領域よりも。prepareToDraw メソッドを使用して、事前にビットマップをトリガーして GPU 操作をアップロードすることもでき、このメソッドにより、RenderThread がアイドル状態のときに事前にビットマップを完了させることができます。理想的には、画像読み込みライブラリがこれを行うのに役立ちます。画像の読み込みを自分で制御したい場合、または描画時にビットマップのアップロードがトリガーされないようにする必要がある場合は、コード内で prepareToDraw を直接呼び出すことができます。

混乱している学生もいるかもしれません。この最適化はメインスレッドを最適化するものではありません。起動パフォーマンスは最適化されますか? 答えは、メインスレッドを最適化できるためです。起動の最初の数フレームでは、各フレームに時間がかかり、各フレームのタスクは RenderThread 内の DrawFrame タスクとして実行されます。前のフレームのタスクが完了していない場合は、現在のフレームの描画は、nSyncAndDrawFrame の実行時間が長すぎるなど、描画処理が遅くなっていることがメインスレッドに反映されます。

3.3 基礎となるメカニズムの最適化

主に、パフォーマンス指標の最適化とビジネス価値の活用という目標を達成するための基盤となるテクノロジーの探索によって行われます。この方向性は比較的リスクとコストがかかります。最終的な決定は、特定の人員条件と最適化効果に基づいて行う必要があります。

Baidu App は VerifyClass の最適化、CPU Booster の最適化、GC 関連の最適化などを試しており、いくつかの技術的な点をまだ調査中です。最適化のこの部分は基本的にグローバル最適化であり、これについてはフォローアップの流暢さのトピックで発表されます。

4. まとめ

スタートアップ パフォーマンスの最適化は、比較的複雑な技術的方向性です。スタートアップ パフォーマンスと密接に関係しているビジネスが数多くあるだけでなく、スタートアップ プロセス中に注意と投資に値するシステム動作も数多くあります。 Baidu アプリの起動パフォーマンスは徐々に向上しており、ボトルネック期に入り、ボトルネックをいかに打破してビジネスと緊密に統合するかが課題であり、パフォーマンスの最適化を開始する機会でもあります。スタートアップ パフォーマンスの最適化は、継続的な学習、継続的な破壊、および継続的な改善のプロセスです。そのプロセスには多くの課題と多くの機会が存在する可能性があります。したがって、スタートアップ パフォーマンスの最適化には終わりがなく、長い道のりがあります。

- 終わり -

参考文献:

1.Douyin 起動の最適化

https://heapdump.cn/article/3624814

2. Kuaishou TTI ガバナンス経験の共有

https://zhuanlan.zhihu.com/p/422859543

3. Android起動最適化の解析

https://juejin.cn/post/7183144743411384375

4、MMKV:

https://github.com/Tencent/MMKV/wiki/android_ipc

推奨読書:

php5.6からgolang1.19へ - ライブラリアプリのパフォーマンス移行への道

モバイル端末における光のスイープモーション効果の応用実践

Android SDKのセキュリティ強化の問題と分析

検索セマンティックモデルの大規模定量的実践

効率的な分散ログ サービス プラットフォームを設計する方法

ビデオおよび画像検索におけるマルチモーダルセマンティックマッチングモデル: 原理、含意、応用および展望

おすすめ

転載: blog.csdn.net/lihui49/article/details/131653586