In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
This article will explain in detail how to explore the starting point of Android application in detail. The content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.
Background
As mentioned in the developer documentation, there are three startup states for Android applications, each of which affects the time it takes for the application to display to the user: cold startup, warm startup, or warm startup. Among the three startup states, cold start takes the longest time, and the system and App have more initialization work. If the startup time is too long, it may cause users to score low in the app store, or even abandon app completely, so cold startup speed is one of the very important performance indicators of each app.
In the work of cold start speed optimization, management is a very important part. There are many details to explore how to choose the statistical point and why to choose it. This article mainly explores how the app layer on Android chooses the starting point of process creation.
Brief introduction of three opportunities
The starting point of the creation time of the three App layer processes involved in this paper: Application, Process.getStartElapsedRealTime,/proc/self/stats starttime.
A brief introduction to the following three process creation time starting points:
Application: Application construction method
The starting point for the creation of the process recorded in Process.getStartElapsedRealTime:Framework. This API has version restrictions and cannot be used below Android N.
/ proc/self/stats starttime: the starting point for the creation of processes recorded in the kernel.
The starting time sequence of the creation of the three processes is as follows: / proc/self/stats starttime is earlier than Process.getStartElapsedRealTime and earlier than Application.
Which of the three timing is better? Which can guide the optimization work? Which is closer to the starting point of the desktop creation process when users click on it? With a few questions, move on.
Deep analysis
Take a closer look at three opportunities:
Application timing
Applciation construction method, Android Java code can be the first buried point of the time, Android development of children's shoes will be more familiar with this time, but a lot of repetition.
Process.getStartElapsedRealTime timing
Time sequence overview chart:
The Process.getStartElapsedRealTime assignment API is the handleBindApplication API. The assignment time is when the App process enters the Java world, the process attach to ActivityManagerService, and then returns to the App process through binder call. Details of the principle can continue to read the source code analysis.
Source code parsing:
A note in the source code of Android 8.1.0 (Process.java): 487 / * 488 * Return the {@ link SystemClock#elapsedRealtime ()} at which this process was started.489 * / 490 public static final long getStartElapsedRealtime () {491return sStartElapsedRealtime As can be seen from the description of the source code, Process.getStartElapsedRealTime represents the time when the program was created, and SystemClock#elapsedRealtime represents the real time from boot. Take a look at the assignment time (ActivityThread.java): 5429 private void handleBindApplication (AppBindData data) {. 5436 / / Note when this process has started.5437 Process.setStartTimes (SystemClock.elapsedRealtime (), SystemClock.uptimeMillis ()) HandleBindApplication is called in the message processing of the ActivityThread main thread H, which, as the inner class of ActivityThread, is the Handler of the main thread processing messages. 234 final H mH = new H (); who sent this message and when did it come from? Students who understand the entry function and creation process of Android App may not be difficult to answer this question. For the creation of App, the entry of the Java layer call is the ActivityThread main method. See: 6459 public static void main (String [] args) {... 6478 Looper.prepareMainLooper (); 64796480 ActivityThread thread = new ActivityThread (); 6481 thread.attach (false);... 6494 Looper.loop (); from the code point of view, the main method mainly prepares the main thread message Looper, executes the ActivityThread attach method, and then the main thread starts the message loop. Look at ActivityThread attach:6315 private void attach (boolean system) {6318 if (! system) {6328 final IActivityManager mgr = ActivityManager.getService (); 6329 try {6330 mgr.attachApplication (mAppThread); 6331} catch (RemoteException ex) {6332 throw ex.rethrowFromSystemServer () 6333} as you can see from the code, there is a binder call, which calls AMS's attachApplication, which is in the system_server process and does the following. Take a look at the ActivityManagerService process: 7215 public final void attachApplication (IApplicationThread thread) {7216 synchronized (this) {7219 attachApplicationLocked (thread, callingPid); 7221} 7222} 6911 private final boolean attachApplicationLocked (IApplicationThread thread,6912 int pid) {… 7102 thread.bindApplication (processName, appInfo, providers,7103 app.instr.mClass,7104 profilerInfo, app.instr.mArguments,7105 app.instr.mWatcher,7106 app.instr.mUiAutomationConnection, testMode,7107 mBinderTransactionTrackingEnabled, enableTrackAllocation,7108 isRestrictedBackupMode | |! normalMode, app.persistent 7109 new Configuration (getGlobalConfiguration ()), app.compat,7110 getCommonServicesLocked (app.isolated), 7111 mCoreSettingsObserver.getCoreSettingsLocked (), 7112 buildSerial) The key call: thread.bindApplication, thread is the Binder object, where there is also a binder call Look at the executor: 690 private class ApplicationThread extends IApplicationThread.Stub {899 public final void bindApplication (String processName, ApplicationInfo appInfo,900 List providers, ComponentName instrumentationName,901 ProfilerInfo profilerInfo, Bundle instrumentationArgs,902 IInstrumentationWatcher instrumentationWatcher,903 IUiAutomationConnection instrumentationUiConnection, int debugMode,904 boolean enableBinderTracking, boolean trackAllocation,905 boolean isRestrictedBackupMode, boolean persistent, Configuration config,906 CompatibilityInfo compatInfo, Map services, Bundle coreSettings) 907 String buildSerial) A pplicationThread executes sendMessage (H.BIND_APPLICATION, data) When the message is sent, how does the execution of this part of the binder thread pool of the App process switch to the main thread? 2605 private void sendMessage (int what, Object obj, int arg1, int arg2, boolean async) {2609 Message msg = Message.obtain ();... 2617 mH.sendMessage (msg); 2618} send messages to the Looper of the main thread through mH, which is executed by the main thread, 1462 private class H extends Handler {1473 public static final int BIND_APPLICATION = 110 1580 public void handleMessage (Message msg) {1653 case BIND_APPLICATION:1656 handleBindApplication (data); 1658 break
HandleBindApplication is the starting point for Process.getStartElapsedRealTime to get the creation of the process, and the subsequent logic is the initialization of Application. It can be seen that the timing of Process.getStartElapsedRealTime is earlier than that of Application. The breakpoints in the Application construction method are as follows:
/ proc/self/stats starttime timing
/ proc/self/stats starttime timing is the starting point for the creation of processes recorded in the kernel layer, and is the earliest of the three opportunities. Take a closer look at:
Proc/pid/stat is used to obtain the statistical information of a process, which is in the form of:
In proc/pid/stat statistics, starttime is the 22nd element. What does the value of starttime mean and how is it calculated? Take a look at fs/proc/array.c 's do_task_stat ()
You can see from the kernel code that the value of start_time is real_start_time of task. First, take a look at the nesc_to_clock_t method:
The div_u64_rem method is an unsigned division operation: the divisor is unsigned 64bit, and the divisor is unsigned 32.
From the point of view of the process of calculation, what is the unit of real_start_time divided by 1000000000Universe 100,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 and 100,000,000 respectively. Take a look at the data structure task_struct definition:
Struct timespec start_time; struct timespec real_start_time
There are two times in task_struct: start_time and real_start_time, where the latter contains sleep time. The value for both units of time is ns,/proc/self/stats starttime and the value is real_start_time:
Struct timespec {_ _ time_t tv_sec; / * Seconds. * / long tv_nsec; / * Nanoseconds. * /}
It can be seen that the unit of real_start_time is ns. If you divide real_start_time by 100000000000Universe 10000000, the conversion unit is 10ms. For example, the value read by / proc/self/stats starttime is 100, then it needs to be converted to 100*10ms=1000ms. However, our startup speed is most likely to be calculated with ms, and / proc/self/stats starttime will lose a certain precision. Why does the kernel do this?
In kernel time statistics, one unit is jiffies,jiffies, which is a global variable in the kernel that records the number of beats generated since the system was started. A simple description is the number of clock interrupts initiated by the kernel within 1 second, which is used in kernel to count the running time of the program. The / proc/self/stats starttime unit of statistics is the jiffies, which represents how many kernel clocks have passed since the application was cold started.
So how do we scientifically count and convert the value of / proc/self/stats starttime? Man proc on the Linux system has the following explanation:
(22) starttime llu
The time the process started after system boot. In kernels before Linux 2.6, this value was expressed in jiffies. Since Linux 2.6the value is expressed in clock ticks (divide by sysconf (_ SC_CLK_TCK)).
The format for this field was% lu before Linux 2.6.
We cannot get the constant USER_HZ in the kernel state, but we can get its value through sysconf (_ SC_CLK_TCK) in the user state.
The calculation formula is as follows:
/ proc/self/stats starttime * 1000 / sysconf (_ SC_CLK_TCK), in ms
Some students may say that the value of sysconf (_ SC_CLK_TCK) is 100. you can just use / proc/self/stats starttime * 10, but you need to consider kernel upgrade or kernel customization scenarios. It is the safest way to use sysconf (_ SC_CLK_TCK) to obtain and participate in the calculation.
Another question, / proc/self/stats starttime is from task_struct real_start_time, when is this time initialized? The answer is that when the task_struct data structure is created, that is, when the process is created, that is, the zygote fork opportunity, the fork system call initializes the child process's data structure task_struct, thread stack and other data structures, and interested students can look at the kernel fork source code.
Through the above detailed analysis, we have a more detailed understanding of the three opportunities. In the actual App project, it is recommended to use the combination of Application timing and / proc/self/stats starttime timing as the starting point for application startup.
Application timing is the first place where Android Java code can be buried. Through this starting point, combined with the end point of cold start, we can clearly know the detailed time-consuming of engineering code, which is of great significance for guiding daily optimization work.
/ proc/self/stats starttime timing is the earliest of the three, among which the engineering code is uncontrollably time-consuming, involving initialization of process data structure, thread stack and so on, but at this time the opportunity is closer to the actual feeling of the user and can be used to measure the user startup experience to the greatest extent.
Due to version restrictions, Process.getStartElapsedRealTime cannot be obtained in versions below Android N and cannot take into account all user machines in the market, so the guiding value of this value is not so great. In the optimization work, the top priority is to optimize the performance experience of medium-and low-end machines. If models below Android N are not available, the startup performance of a large number of low-end machines is not within the statistical range.
On how to deeply explore the starting point of Android applications to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.