【Android12】Android性能調優工具SystemServerTiming日志

Android性能調優工具SystemServerTiming日志

性能優化、穩定性優化是Android系統優化的兩大方面,對于性能調試Android提供了很多工具,比如:bootchart、systrace、perfboot、log、dmsg等等。

SystemServerTiming是Android原生系統中一個日志標簽,也就是tag為SystemServerTiming的日志,這類日志信息會輸出到Logd和Trace系統中。可以通過Android logcat 或者 抓取Systrace的方式取得。

SystemServerTiming主要用于記錄SystemServer中啟動各種服務的耗時信息。在性能優化分析的場景下,利用該Log我們分析出SystemServer中各個服務在啟動性能上是否存異常,特別是在SystemServer中自定義追加的Service。

  • SystemServerTiming日志的一段例子
# 示意log日志
11-20 23:58:20.766 21530 21530 I SystemServerTiming: InitBeforeStartServices
.................. 21530 21530 I SystemServerTiming: StartServices
.................. 21530 21530 I SystemServerTiming: startBootstrapServices
.................. 21530 21530 I SystemServerTiming: StartWatchdog
.................. 21530 21530 I SystemServerTiming: ReadingSystemConfig
.................. 21530 21530 I SystemServerTiming: PlatformCompat
.................. 21530 21530 I SystemServerTiming: StartFileIntegrityService
.................. 21530 21530 I SystemServerTiming: StartInstaller
.................. 21530 21530 I SystemServerTiming: DeviceIdentifiersPolicyService
.................. 21530 21530 I SystemServerTiming: UriGrantsManagerService
.................. 21530 21530 I SystemServerTiming: StartPowerStatsService
.................. 21530 21530 I SystemServerTiming: StartIStatsService
.................. 21530 21530 I SystemServerTiming: MemtrackProxyService
# 非User編譯模式下,會輸出統計每個階段耗時的Log
.................. 21530 21530 I SystemServerTiming: InitBeforeStartServices took to complete: ***ms
...
.................. 21530 21530 I SystemServerTiming: startCoreServices
...
.................. 21530 21530 I SystemServerTiming: startOtherServices
.................. 21530 21530 I SystemServerTiming: SecondaryZygotePreload
...
.................. 21530 21530 I SystemServerTiming: StartSystemUI
  • SystemServerTiming日志的源碼實現
    TimingsTraceAndSlog.java源文件中,定義了SystemServerTiming日志標簽,并通過Slog(輸出到Logd的System分區)和Trace實現日志的輸出。
    源碼路徑:/frameworks/base/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
/** Copyright (C) 2019 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.android.server.utils;import android.annotation.NonNull;
import android.os.Trace;
import android.util.Slog;
import android.util.TimingsTraceLog;/*** Helper class for reporting boot and shutdown timing metrics, also logging to {@link Slog}.*/
public final class TimingsTraceAndSlog extends TimingsTraceLog {/*** Tag for timing measurement of main thread.*/public static final String SYSTEM_SERVER_TIMING_TAG = "SystemServerTiming";/*** Tag for timing measurement of non-main asynchronous operations.*/private static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async";/*** Set this to a positive value to get a {@Slog.w} log for any trace that took longer than it.*/private static final long BOTTLENECK_DURATION_MS = -1;private final String mTag;/*** Creates a new {@link TimingsTraceAndSlog} for async operations.*/@NonNullpublic static TimingsTraceAndSlog newAsyncLog() {return new TimingsTraceAndSlog(SYSTEM_SERVER_TIMING_ASYNC_TAG,Trace.TRACE_TAG_SYSTEM_SERVER);}/*** Default constructor using {@code system_server} tags.*/public TimingsTraceAndSlog() {this(SYSTEM_SERVER_TIMING_TAG);}/*** Custom constructor using {@code system_server} trace tag.** @param tag {@code logcat} tag*/public TimingsTraceAndSlog(@NonNull String tag) {this(tag, Trace.TRACE_TAG_SYSTEM_SERVER);}/*** Custom constructor.** @param tag {@code logcat} tag* @param traceTag {@code atrace} tag*/public TimingsTraceAndSlog(@NonNull String tag, long traceTag) {super(tag, traceTag);mTag = tag;}@Overridepublic void traceBegin(@NonNull String name) {// 使用Slog的Info級別輸出Slog.i(mTag, name);// 調用父類TimingsTraceLog接口,輸出Tracesuper.traceBegin(name);}@Overridepublic void logDuration(String name, long timeMs) {super.logDuration(name, timeMs);if (BOTTLENECK_DURATION_MS > 0 && timeMs >= BOTTLENECK_DURATION_MS) {Slog.w(mTag, "Slow duration for " + name + ": " + timeMs + "ms");}}@Overridepublic String toString() {return "TimingsTraceAndSlog[" + mTag + "]";}
}

父類TimingsTraceLog 中的相關實現。

/** Copyright (C) 2016 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.util;import android.annotation.NonNull;
import android.os.Build;
import android.os.SystemClock;
import android.os.Trace;import com.android.internal.annotations.VisibleForTesting;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*** Helper class for reporting boot and shutdown timing metrics.** <p><b>NOTE:</b> This class is not thread-safe. Use a separate copy for other threads.** @hide*/
public class TimingsTraceLog {// Debug boot time for every step if it's non-user build.// 注意:只有在非user編譯下,才會輸出每個階段的耗時信息(耗時信息,也可以通過查看log日志的時間戳)private static final boolean DEBUG_BOOT_TIME = !Build.IS_USER;// Maximum number of nested calls that are storedprivate static final int MAX_NESTED_CALLS = 10;private final String[] mStartNames;private final long[] mStartTimes;private final String mTag;private final long mTraceTag;private final long mThreadId;private final int mMaxNestedCalls;private int mCurrentLevel = -1;public TimingsTraceLog(String tag, long traceTag) {this(tag, traceTag, DEBUG_BOOT_TIME ? MAX_NESTED_CALLS : -1);}@VisibleForTestingpublic TimingsTraceLog(String tag, long traceTag, int maxNestedCalls) {mTag = tag;mTraceTag = traceTag;mThreadId = Thread.currentThread().getId();mMaxNestedCalls = maxNestedCalls;if (maxNestedCalls > 0) {mStartNames = new String[maxNestedCalls];mStartTimes = new long[maxNestedCalls];} else {mStartNames = null;mStartTimes = null;}}/*** Begin tracing named section* @param name name to appear in trace*/public void traceBegin(String name) {assertSameThread();Trace.traceBegin(mTraceTag, name);if (!DEBUG_BOOT_TIME) return;if (mCurrentLevel + 1 >= mMaxNestedCalls) {Slog.w(mTag, "not tracing duration of '" + name + "' because already reached "+ mMaxNestedCalls + " levels");return;}mCurrentLevel++;mStartNames[mCurrentLevel] = name;mStartTimes[mCurrentLevel] = SystemClock.elapsedRealtime();}/*** End tracing previously {@link #traceBegin(String) started} section.** <p>Also {@link #logDuration logs} the duration.*/public void traceEnd() {assertSameThread();Trace.traceEnd(mTraceTag);if (!DEBUG_BOOT_TIME) return;if (mCurrentLevel < 0) {Slog.w(mTag, "traceEnd called more times than traceBegin");return;}final String name = mStartNames[mCurrentLevel];final long duration = SystemClock.elapsedRealtime() - mStartTimes[mCurrentLevel];mCurrentLevel--;logDuration(name, duration);}private void assertSameThread() {final Thread currentThread = Thread.currentThread();if (currentThread.getId() != mThreadId) {throw new IllegalStateException("Instance of TimingsTraceLog can only be called from "+ "the thread it was created on (tid: " + mThreadId + "), but was from "+ currentThread.getName() + " (tid: " + currentThread.getId() + ")");}}/*** Logs a duration so it can be parsed by external tools for performance reporting.*/public void logDuration(String name, long timeMs) {Slog.d(mTag, name + " took to complete: " + timeMs + "ms");}/*** Gets the names of the traces that {@link #traceBegin(String) have begun} but* {@link #traceEnd() have not finished} yet.** <p><b>NOTE:</b> this method is expensive and it should not be used in "production" - it* should only be used for debugging purposes during development (and/or guarded by* static {@code DEBUG} constants that are {@code false}).*/@NonNullpublic final List<String> getUnfinishedTracesForDebug() {if (mStartTimes == null || mCurrentLevel < 0) return Collections.emptyList();final ArrayList<String> list = new ArrayList<>(mCurrentLevel + 1);for (int i = 0; i <= mCurrentLevel; i++) {list.add(mStartNames[i]);}return list;}
}
  • SystemServer中輸出SystemServerTiming日志。SystemServer會在其run函數中創建TimingsTraceAndSlog對象,然后調用這個對象的traceBegin和traceEnd函數。
// frameworks/base/services/java/com/android/server/SystemServer.javaprivate void run() {TimingsTraceAndSlog t = new TimingsTraceAndSlog();try {// 使用SystemServerTiming日志標簽輸出t.traceBegin("InitBeforeStartServices");// 省略....// Start services.try {t.traceBegin("StartServices");startBootstrapServices(t);startCoreServices(t);startOtherServices(t);} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}// 省略... 
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716853.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716853.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716853.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《Spring Security 簡易速速上手小冊》第10章 未來趨勢與高級話題(2024 最新版)

文章目錄 10.1 云原生安全性趨勢10.1.1 基礎知識10.1.2 重點案例&#xff1a;保護微服務通信10.1.3 拓展案例 1&#xff1a;容器安全最佳實踐10.1.4 拓展案例 2&#xff1a;自動化安全審計和合規性檢查 10.2 反應式編程與 Spring Security10.2.1 基礎知識10.2.2 重點案例&#…

nginx-圖片模塊

./configure --with-http_image_filter_module location / {root html;index index.html index.htm;if ($arg_w "") {set $arg_w -;}if ($arg_h "") {set $arg_h -;}image_filter resize $arg_w $arg_h;image_filter_jpeg_quality 95; } 訪問: 1234…

CSS錐形漸變:conic-gradient()

畫一個扇形圖&#xff0c;使用常規方法可能很難畫&#xff0c;但是用錐形漸變的話非常好畫 <style>.pattern{width: 100px; height: 100px;border-radius: 50%;background: conic-gradient(yellow 30deg , black 30deg , black 90deg , yellow 90deg ,yellow 150d…

Git分布式版本控制系統——git學習準備工作

一、Git倉庫介紹 開發者可以通過Git倉庫來存儲和管理文件代碼&#xff0c;Git倉庫分為兩種&#xff1a; 本地倉庫&#xff1a;開發人員自己電腦上的Git倉庫 遠程倉庫&#xff1a;遠程服務器上的Git倉庫 倉庫之間的運轉如下圖&#xff1a; commit&#xff1a;提交&#xff…

Decoupled Knowledge Distillation解耦知識蒸餾

Decoupled Knowledge Distillation解耦知識蒸餾 現有的蒸餾方法主要是基于從中間層提取深層特征&#xff0c;而忽略了Logit蒸餾的重要性。為了給logit蒸餾研究提供一個新的視角&#xff0c;我們將經典的KD損失重新表述為兩部分&#xff0c;即目標類知識蒸餾&#xff08;TCKD&a…

c++之旅——第四彈

大家好啊&#xff0c;這里是c之旅第三彈&#xff0c;跟隨我的步伐來開始這一篇的學習吧&#xff01; 如果有知識性錯誤&#xff0c;歡迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 創作不易&#xff0c;希望大家多多支持哦&#xff01; 本篇文章的主…

如何對比 MySQL 主備數據的一致性?

隨著業務范圍的擴大&#xff0c;很多企業為了保障核心業務的高可用性&#xff0c;選擇了 MySQL 主從架構&#xff0c;這一套方案通常具備主備數據同步、數據備份與恢復、讀寫分離、高可用切換等特性&#xff0c;是一種相當成熟可靠的數據庫架構方案。然而這套方案在特定情況下可…

Redis小白入門教程

Redis入門教程 1. Redis入門1.1 Redis簡介1.2 Redis服務啟動與停止1.2.1 Redis下載1.2.2 服務啟動命令1.2.3 客戶端連接命令1.2.4 修改Redis配置文件 2. Redis數據類型2.1 五種常用數據類型介紹2.1.1 字符串操作命令2.1.2 哈希操作命令2.1.3 列表操作命令2.1.4 集合操作命令2.1…

雙周回顧#006 - 這三個月

斷更啦~~ 上次更新時間 2023/11/23, 斷更近三個月的時間。 先狡辯下&#xff0c;因為忙、著實忙。因為忙&#xff0c;心安理得給斷更找了個借口&#xff0c;批評下自己~~ 這三個月在做啥&#xff1f;跨部門援助&#xff0c;支援公司互聯網的 ToC 項目&#xff0c;一言難盡。 …

智能時代:人工智能引領未來創新

智能時代&#xff1a;人工智能引領未來創新 1. 人工智能的定義與特點 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指模擬、延伸和擴展人類智能的理論、方法、技術及應用系統的一門交叉學科。其特點包括學習能力、推理能力、感知能力和交互能力…

【C語言】InfiniBand 驅動mlx4_ib_init和mlx4_ib_cleanup

一、中文講解 這兩個函數是Linux內核模塊中對于Mellanox InfiniBand 驅動程序初始化和清理的函數。 mlx4_ib_init()函數是模塊初始化函數&#xff0c;使用__init宏標注&#xff0c;表示該函數只在模塊加載時運行一次。 函數執行的步驟如下&#xff1a; 1. 通過alloc_ordered_w…

數據結構——lesson5棧和隊列詳解

hellohello~這里是土土數據結構學習筆記&#x1f973;&#x1f973; &#x1f4a5;個人主頁&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所屬專欄&#xff1a;數據結構學習筆記 &#x1f4a5;對于順序表鏈表有疑問的都可以在上面數據結構的專欄進行學習哦~感謝大家的觀看與…

ElasticSearch開篇

1.ElasticSearch簡介 1.1 ElasticSearch&#xff08;簡稱ES&#xff09; Elasticsearch是用Java開發并且是當前最流行的開源的企業級搜索引擎。能夠達到實時搜索&#xff0c;穩定&#xff0c;可靠&#xff0c;快速&#xff0c;安裝使用方便。 1.2 ElasticSearch與Lucene的關…

Angular項目升級的一般步驟?

升級Angular項目是一個重要的任務&#xff0c;可以帶來性能改進、新功能和安全性增強等好處。以下是升級Angular項目的一般步驟&#xff1a; 1、備份項目文件&#xff1a; 在進行升級之前&#xff0c;務必對整個項目進行備份&#xff0c;以防意外情況發生。 2、查看當前版本&…

如何快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中?教你使用寶塔Linux面板遷移網站

要快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中&#xff0c;可以遵循以下步驟&#xff1a; 準備遷移前的工作&#xff1a;首先&#xff0c;確保你已經有了從其他云服務器到騰訊云輕量應用服務器的數據備份。這一步是為了在遷移過程中避免數據丟失或損壞。 使用寶…

模擬器抓HTTP/S的包時如何繞過單向證書校驗(XP框架)

模擬器抓HTTP/S的包時如何繞過單向證書校驗&#xff08;XP框架&#xff09; 逍遙模擬器無法激活XP框架來繞過單向的證書校驗&#xff0c;如下圖&#xff1a; ?? 解決辦法&#xff1a; 安裝JustMePlush.apk安裝Just Trust Me.apk安裝RE管理器.apk安裝Xposedinstaller_逍遙64位…

智能邊緣小站 CloudPond(低延遲、高帶寬和更好的數據隱私保護)

智能邊緣小站 CloudPond(低延遲、高帶寬和更好的數據隱私保護) 邊緣小站的主要功能是管理用戶在線下部署的整機柜設施&#xff0c;一個邊緣小站關聯一個華為云指定的區域和一個用戶指定的場地&#xff0c;相關的資源運行狀況監控等。 邊緣計算 邁入5G和AI時代&#xff0c;新…

利用redis實現秒殺功能

6、秒殺優化 這個是 圖靈 的redis實戰里面的一個案例 6.1 秒殺優化-異步秒殺思路 我們來回顧一下下單流程 當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟…

基于單片機的紅外遙控解碼程序設計與實現

摘要:該文介紹基于士蘭半導體芯片(SC6122)的紅外發射遙控器,通過單片機解碼程序,實現紅外遙控信號的解碼和接收。紅外接收頭與單片機特定的引腳連接,通過設置單片機定時計數器,采樣來自紅外接收頭的高、低電平寬度解碼遙控信號。該解碼程序設計主要應用在LED數碼顯示控制…

電機的極數和槽數,機械角度和電角度,霍爾IC,內外轉子

什么是電機的極數和槽數&#xff1f; 【第7集】②?正弦波驅動的轉矩脈動、正弦電流的時序和相位變化、超前角控制&#xff08;超前角調整&#xff09;、正弦波驅動的各種波形 - 電源設計電子電路基礎電源技術信息網站_羅姆電源設計R課堂 (rohm.com.cn) 下面為您介紹表示電機…