Time consuming of code point statistics application

Keywords: Mobile shell Fragment Database

In mobile application development, we sometimes need to monitor the time-consuming of some processes, such as application startup time, page Jump time, etc., which is not accurate only by naked eyes. We can realize it in several ways. One way is to obtain startup time by shell, one way is to output time by code point tapping, and the other way is to insert a stake. Here is a brief introduction The first two.

I. adb shell am mode

Make the adb shell get the real start time code of the application as follows:

adb shell am start -W [packageName]/[packageName.SplashActivity]

After execution, you will get three times: ThisTime, TotalTime and WaitTime. TotalTime represents the start time of the Application, including the creation process + Application initialization + Activity initialization to the interface display.

II. Code management

The execution time of each method can be accurately obtained through code marking. The relevant codes are as follows:

/**
 * The time-consuming monitor object records the time-consuming situation of the whole process, which can be used in many places requiring statistics, such as Activity startup time and Fragment startup time.
 */
public class TimeMonitor {
    private final String TAG = TimeMonitor.class.getSimpleName();
    private int mMonitorId = -1;
    private HashMap<String, Long> mTimeTag = new HashMap<>();
    private long mStartTime = 0;

    public TimeMonitor(int mMonitorId) {
        Log.d(TAG, "init TimeMonitor id: " + mMonitorId);
        this.mMonitorId = mMonitorId;
    }

    public int getMonitorId() {
        return mMonitorId;
    }

    public void startMonitor() {
        //Clear the previous data every time you restart to avoid statistical errors
        if (mTimeTag.size() > 0) {
            mTimeTag.clear();
        }
        mStartTime = System.currentTimeMillis();
    }

    /**
     * Record the time consumption of a certain tag every time you hit a point
     */
    public void recordingTimeTag(String tag) {
        //If the same tag has been saved, clear it first
        if (mTimeTag.get(tag) != null) {
            mTimeTag.remove(tag);
        }
        long time = System.currentTimeMillis() - mStartTime;
        Log.d(TAG, tag + ": " + time);
        mTimeTag.put(tag, time);
    }

    public void end(String tag, boolean writeLog) {
        recordingTimeTag(tag);
        end(writeLog);
    }

    public void end(boolean writeLog) {
        if (writeLog) {
            //Write to local file
        }
    }

    public HashMap<String, Long> getTimeTags() {
        return mTimeTag;
    }
}
/**
 * Click configuration class, which is used to count the time-consuming of each stage and facilitate code maintenance and management.
 */
public final class TimeMonitorConfig {
    //Application startup time
    public static final int TIME_MONITOR_ID_APPLICATION_START = 1;
}
/**
 * A single case is used to manage the time-consuming statistical data.
 */
public class TimeMonitorManager {
    private static TimeMonitorManager mTimeMonitorManager = null;
    private HashMap<Integer, TimeMonitor> mTimeMonitorMap = null;

    public synchronized static TimeMonitorManager getInstance() {
        if (mTimeMonitorManager == null) {
            mTimeMonitorManager = new TimeMonitorManager();
        }
        return mTimeMonitorManager;
    }

    public TimeMonitorManager() {
        this.mTimeMonitorMap = new HashMap<Integer, TimeMonitor>();
    }

    /**
     * Initialize the dotting module
     */
    public void resetTimeMonitor(int id) {
        if (mTimeMonitorMap.get(id) != null) {
            mTimeMonitorMap.remove(id);
        }
        getTimeMonitor(id);
    }

    /**
     * Get puncher
     */
    public TimeMonitor getTimeMonitor(int id) {
        TimeMonitor monitor = mTimeMonitorMap.get(id);
        if (monitor == null) {
            monitor = new TimeMonitor(id);
            mTimeMonitorMap.put(id, monitor);
        }
        return monitor;
    }
}

Generally, the points are:

Application lifecycle nodes, such as onCreate of application, callback function of Activity or Fragment (onCreate, onResume, etc.);
Important initialization methods are needed at startup, such as database initialization, reading some local data, etc.
Other time-consuming algorithms, etc.

For example, add monitoring at startup and statistics at Application and the first Activity.

Application:

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    TimeMonitorManager.getInstance().resetTimeMonitor(TimeMonitorConfig.TIME_MONITOR_ID_APPLICATION_START);
}
  
@Override
public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    TimeMonitorManager.getInstance().getTimeMonitor(TimeMonitorConfig.TIME_MONITOR_ID_APPLICATION_START).recordingTimeTag("Application-onCreate");
}

First Activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    TimeMonitorManager.getInstance().getTimeMonitor(TimeMonitorConfig.TIME_MONITOR_ID_APPLICATION_START).recordingTimeTag("SplashActivity-onCreate");
    super.onCreate(savedInstanceState);
    init();
    TimeMonitorManager.getInstance().getTimeMonitor(TimeMonitorConfig.TIME_MONITOR_ID_APPLICATION_START).recordingTimeTag("SplashActivity-onCreate-Over");
}

@Override
protected void onStart() {
    super.onStart();
    TimeMonitorManager.getInstance().getTimeMonitor(TimeMonitorConfig.TIME_MONITOR_ID_APPLICATION_START).end("SplashActivity-onStart", false);
}

Posted by bdcode on Wed, 11 Dec 2019 08:46:10 -0800