Choosing the Best Android Process‑Start Timestamp for Cold‑Start Optimization
The article examines Android cold‑start performance by comparing three process‑creation timestamps—Application <init>, Process.getStartElapsedRealTime, and /proc/self/stat starttime—detailing their origins, extraction methods, conversion formulas, and practical guidance on which to use for accurate startup measurement.
Background
Developer documentation defines three Android app launch states—cold, warm, and hot—each affecting the time required to display the app to the user. Cold start is the longest because the system and app perform extensive initialization. Excessive cold‑start time can lead to low ratings or abandonment, making it a critical performance metric.
Three Timing Points Overview
The article focuses on three process‑creation timestamps that can serve as the starting point for measuring cold start:
Application <init> : the constructor of the Application class; the earliest Java‑level hook for inserting trace points.
Process.getStartElapsedRealTime : a framework‑recorded start time; unavailable on Android versions prior to N.
/proc/self/stat starttime : the kernel‑recorded start time; the earliest of the three.
The chronological order is: /proc/self/stat starttime → Process.getStartElapsedRealTime → Application <init>.
In‑Depth Analysis
Application <init> Timing
The Application constructor runs in the Java layer and is the most familiar point for developers to place instrumentation. It marks the moment when the Android runtime begins executing app‑specific Java code.
Process.getStartElapsedRealTime Timing
This timestamp is set in the framework’s handleBindApplication method, which runs after the process has attached to the ActivityManagerService and the binder call returns to the app process. The relevant source excerpt:
Android 8.1.0 source (Process.java):
/**
* Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
*/
public static final long getStartElapsedRealtime() {
return sStartElapsedRealtime;
}
// In ActivityThread.handleBindApplication:
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());The handleBindApplication call ultimately triggers Process.setStartTimes, establishing the start point earlier than the Application constructor.
/proc/self/stat starttime Timing
This is the kernel‑level timestamp recorded in /proc/self/stat. The 22nd field of the stat file contains starttime, which corresponds to task_struct.real_start_time measured in nanoseconds.
The kernel stores this value in jiffies (ticks since boot). Converting it to milliseconds requires the system’s clock‑tick frequency:
struct timespec {
__time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds */
};Conversion formula (as described in man proc):
ms = starttime * 1000 / sysconf(_SC_CLK_TCK);Because _SC_CLK_TCK is typically 100 on many kernels, a shortcut of starttime * 10 yields milliseconds, but using sysconf(_SC_CLK_TCK) is safer across kernel versions.
The timestamp originates when the task_struct for the new process is created during the Zygote fork, making it the closest representation of the moment the user’s click initiates process creation.
Summary
Application <init> is the earliest Java hook; combining it with the cold‑start end point provides fine‑grained insight into app‑level execution time.
/proc/self/stat starttime is the earliest overall timestamp and reflects the user‑perceived startup experience most accurately.
Process.getStartElapsedRealTime is unavailable on Android N and below, limiting its usefulness for low‑end devices.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
