Merge "Add clock-type to choose how timestamps are provided when profiling" am: beefb571f6 am: 6c7314dcd6
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2401636 Change-Id: I6ab8b98713a437655ae445fc948da9a6534d2b3c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -927,6 +927,7 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
int samplingInterval;
|
||||
boolean autoStopProfiler;
|
||||
boolean streamingOutput;
|
||||
int mClockType;
|
||||
boolean profiling;
|
||||
boolean handlingProfiling;
|
||||
public void setProfiler(ProfilerInfo profilerInfo) {
|
||||
@@ -953,6 +954,7 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
samplingInterval = profilerInfo.samplingInterval;
|
||||
autoStopProfiler = profilerInfo.autoStopProfiler;
|
||||
streamingOutput = profilerInfo.streamingOutput;
|
||||
mClockType = profilerInfo.clockType;
|
||||
}
|
||||
public void startProfiling() {
|
||||
if (profileFd == null || profiling) {
|
||||
@@ -961,8 +963,8 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
try {
|
||||
int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
|
||||
VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
|
||||
bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval,
|
||||
streamingOutput);
|
||||
bufferSize * 1024 * 1024, mClockType, samplingInterval != 0,
|
||||
samplingInterval, streamingOutput);
|
||||
profiling = true;
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "Profiling failed on path " + profileFile, e);
|
||||
@@ -6511,6 +6513,7 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
|
||||
mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
|
||||
mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
|
||||
mProfiler.mClockType = data.initProfilerInfo.clockType;
|
||||
if (data.initProfilerInfo.attachAgentDuringBind) {
|
||||
agent = data.initProfilerInfo.agent;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,17 @@ import java.util.Objects;
|
||||
*/
|
||||
public class ProfilerInfo implements Parcelable {
|
||||
|
||||
// CLOCK_TYPE_DEFAULT chooses the default used by ART. ART uses CLOCK_TYPE_DUAL by default (see
|
||||
// kDefaultTraceClockSource in art/runtime/runtime_globals.h).
|
||||
public static final int CLOCK_TYPE_DEFAULT = 0x000;
|
||||
// The values of these constants are chosen such that they correspond to the flags passed to
|
||||
// VMDebug.startMethodTracing to choose the corresponding clock type (see
|
||||
// core/java/android/app/ActivityThread.java).
|
||||
// The flag values are defined in ART (see TraceFlag in art/runtime/trace.h).
|
||||
public static final int CLOCK_TYPE_WALL = 0x010;
|
||||
public static final int CLOCK_TYPE_THREAD_CPU = 0x100;
|
||||
public static final int CLOCK_TYPE_DUAL = 0x110;
|
||||
|
||||
private static final String TAG = "ProfilerInfo";
|
||||
|
||||
/* Name of profile output file. */
|
||||
@@ -66,13 +77,20 @@ public class ProfilerInfo implements Parcelable {
|
||||
*/
|
||||
public final boolean attachAgentDuringBind;
|
||||
|
||||
/**
|
||||
* Indicates the clock source to be used for profiling. The source could be wallclock, thread
|
||||
* cpu or both
|
||||
*/
|
||||
public final int clockType;
|
||||
|
||||
public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
|
||||
boolean streaming, String agent, boolean attachAgentDuringBind) {
|
||||
boolean streaming, String agent, boolean attachAgentDuringBind, int clockType) {
|
||||
profileFile = filename;
|
||||
profileFd = fd;
|
||||
samplingInterval = interval;
|
||||
autoStopProfiler = autoStop;
|
||||
streamingOutput = streaming;
|
||||
this.clockType = clockType;
|
||||
this.agent = agent;
|
||||
this.attachAgentDuringBind = attachAgentDuringBind;
|
||||
}
|
||||
@@ -85,6 +103,25 @@ public class ProfilerInfo implements Parcelable {
|
||||
streamingOutput = in.streamingOutput;
|
||||
agent = in.agent;
|
||||
attachAgentDuringBind = in.attachAgentDuringBind;
|
||||
clockType = in.clockType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for the clock type corresponding to the option string passed to the activity
|
||||
* manager. am profile start / am start-activity start-profiler commands accept clock-type
|
||||
* option to choose the source of timestamps when profiling. This function maps the option
|
||||
* string to the value of flags that is used when calling VMDebug.startMethodTracing
|
||||
*/
|
||||
public static int getClockTypeFromString(String type) {
|
||||
if ("thread-cpu".equals(type)) {
|
||||
return CLOCK_TYPE_THREAD_CPU;
|
||||
} else if ("wall".equals(type)) {
|
||||
return CLOCK_TYPE_WALL;
|
||||
} else if ("dual".equals(type)) {
|
||||
return CLOCK_TYPE_DUAL;
|
||||
} else {
|
||||
return CLOCK_TYPE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +130,8 @@ public class ProfilerInfo implements Parcelable {
|
||||
*/
|
||||
public ProfilerInfo setAgent(String agent, boolean attachAgentDuringBind) {
|
||||
return new ProfilerInfo(this.profileFile, this.profileFd, this.samplingInterval,
|
||||
this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind);
|
||||
this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind,
|
||||
this.clockType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +171,7 @@ public class ProfilerInfo implements Parcelable {
|
||||
out.writeInt(streamingOutput ? 1 : 0);
|
||||
out.writeString(agent);
|
||||
out.writeBoolean(attachAgentDuringBind);
|
||||
out.writeInt(clockType);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -146,6 +185,7 @@ public class ProfilerInfo implements Parcelable {
|
||||
proto.write(ProfilerInfoProto.AUTO_STOP_PROFILER, autoStopProfiler);
|
||||
proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput);
|
||||
proto.write(ProfilerInfoProto.AGENT, agent);
|
||||
proto.write(ProfilerInfoProto.CLOCK_TYPE, clockType);
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
@@ -170,6 +210,7 @@ public class ProfilerInfo implements Parcelable {
|
||||
streamingOutput = in.readInt() != 0;
|
||||
agent = in.readString();
|
||||
attachAgentDuringBind = in.readBoolean();
|
||||
clockType = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -186,7 +227,8 @@ public class ProfilerInfo implements Parcelable {
|
||||
&& autoStopProfiler == other.autoStopProfiler
|
||||
&& samplingInterval == other.samplingInterval
|
||||
&& streamingOutput == other.streamingOutput
|
||||
&& Objects.equals(agent, other.agent);
|
||||
&& Objects.equals(agent, other.agent)
|
||||
&& clockType == other.clockType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,6 +239,7 @@ public class ProfilerInfo implements Parcelable {
|
||||
result = 31 * result + (autoStopProfiler ? 1 : 0);
|
||||
result = 31 * result + (streamingOutput ? 1 : 0);
|
||||
result = 31 * result + Objects.hashCode(agent);
|
||||
result = 31 * result + clockType;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,5 @@ message ProfilerInfoProto {
|
||||
optional bool streaming_output = 5;
|
||||
// Denotes an agent (and its parameters) to attach for profiling.
|
||||
optional string agent = 6;
|
||||
optional int32 clock_type = 7;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,6 @@ import android.os.ServiceManager;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -175,6 +174,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
private boolean mStreaming; // Streaming the profiling output to a file.
|
||||
private String mAgent; // Agent to attach on startup.
|
||||
private boolean mAttachAgentDuringBind; // Whether agent should be attached late.
|
||||
private int mClockType; // Whether we need thread cpu / wall clock / both.
|
||||
private int mDisplayId;
|
||||
private int mTaskDisplayAreaFeatureId;
|
||||
private int mWindowingMode;
|
||||
@@ -400,6 +400,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
mAutoStop = false;
|
||||
} else if (opt.equals("--sampling")) {
|
||||
mSamplingInterval = Integer.parseInt(getNextArgRequired());
|
||||
} else if (opt.equals("--clock-type")) {
|
||||
String clock_type = getNextArgRequired();
|
||||
mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
|
||||
} else if (opt.equals("--streaming")) {
|
||||
mStreaming = true;
|
||||
} else if (opt.equals("--attach-agent")) {
|
||||
@@ -548,7 +551,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
}
|
||||
}
|
||||
profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
|
||||
mStreaming, mAgent, mAttachAgentDuringBind);
|
||||
mStreaming, mAgent, mAttachAgentDuringBind, mClockType);
|
||||
}
|
||||
|
||||
pw.println("Starting: " + intent);
|
||||
@@ -878,24 +881,15 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void removeWallOption() {
|
||||
String props = SystemProperties.get("dalvik.vm.extra-opts");
|
||||
if (props != null && props.contains("-Xprofile:wallclock")) {
|
||||
props = props.replace("-Xprofile:wallclock", "");
|
||||
props = props.trim();
|
||||
SystemProperties.set("dalvik.vm.extra-opts", props);
|
||||
}
|
||||
}
|
||||
|
||||
private int runProfile(PrintWriter pw) throws RemoteException {
|
||||
final PrintWriter err = getErrPrintWriter();
|
||||
String profileFile = null;
|
||||
boolean start = false;
|
||||
boolean wall = false;
|
||||
int userId = UserHandle.USER_CURRENT;
|
||||
int profileType = 0;
|
||||
mSamplingInterval = 0;
|
||||
mStreaming = false;
|
||||
mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT;
|
||||
|
||||
String process = null;
|
||||
|
||||
@@ -907,8 +901,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
while ((opt=getNextOption()) != null) {
|
||||
if (opt.equals("--user")) {
|
||||
userId = UserHandle.parseUserArg(getNextArgRequired());
|
||||
} else if (opt.equals("--wall")) {
|
||||
wall = true;
|
||||
} else if (opt.equals("--clock-type")) {
|
||||
String clock_type = getNextArgRequired();
|
||||
mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
|
||||
} else if (opt.equals("--streaming")) {
|
||||
mStreaming = true;
|
||||
} else if (opt.equals("--sampling")) {
|
||||
@@ -956,29 +951,12 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
return -1;
|
||||
}
|
||||
profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
|
||||
null, false);
|
||||
null, false, mClockType);
|
||||
}
|
||||
|
||||
try {
|
||||
if (wall) {
|
||||
// XXX doesn't work -- this needs to be set before booting.
|
||||
String props = SystemProperties.get("dalvik.vm.extra-opts");
|
||||
if (props == null || !props.contains("-Xprofile:wallclock")) {
|
||||
props = props + " -Xprofile:wallclock";
|
||||
//SystemProperties.set("dalvik.vm.extra-opts", props);
|
||||
}
|
||||
} else if (start) {
|
||||
//removeWallOption();
|
||||
}
|
||||
if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
|
||||
wall = false;
|
||||
err.println("PROFILE FAILED on process " + process);
|
||||
return -1;
|
||||
}
|
||||
} finally {
|
||||
if (!wall) {
|
||||
//removeWallOption();
|
||||
}
|
||||
if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
|
||||
err.println("PROFILE FAILED on process " + process);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3456,8 +3434,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println(" help");
|
||||
pw.println(" Print this help text.");
|
||||
pw.println(" start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
|
||||
pw.println(" [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]");
|
||||
pw.println(" [--track-allocation] [--user <USER_ID> | current] <INTENT>");
|
||||
pw.println(" [--sampling INTERVAL] [--clock-type <TYPE>] [--streaming]");
|
||||
pw.println(" [-R COUNT] [-S] [--track-allocation]");
|
||||
pw.println(" [--user <USER_ID> | current] <INTENT>");
|
||||
pw.println(" Start an Activity. Options are:");
|
||||
pw.println(" -D: enable debugging");
|
||||
pw.println(" -N: enable native debugging");
|
||||
@@ -3465,6 +3444,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println(" --start-profiler <FILE>: start profiler and send results to <FILE>");
|
||||
pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
|
||||
pw.println(" between samples (use with --start-profiler)");
|
||||
pw.println(" --clock-type <TYPE>: type can be wall / thread-cpu / dual. Specify");
|
||||
pw.println(" the clock that is used to report the timestamps when profiling");
|
||||
pw.println(" The default value is dual. (use with --start-profiler)");
|
||||
pw.println(" --streaming: stream the profiling output to the specified file");
|
||||
pw.println(" (use with --start-profiler)");
|
||||
pw.println(" -P <FILE>: like above, but profiling stops when app goes idle");
|
||||
@@ -3542,12 +3524,16 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println(" stop: stop tracing IPC transactions and dump the results to file.");
|
||||
pw.println(" --dump-file <FILE>: Specify the file the trace should be dumped to.");
|
||||
pw.println(" profile start [--user <USER_ID> current]");
|
||||
pw.println(" [--clock-type <TYPE>]");
|
||||
pw.println(" [--sampling INTERVAL | --streaming] <PROCESS> <FILE>");
|
||||
pw.println(" Start profiler on a process. The given <PROCESS> argument");
|
||||
pw.println(" may be either a process name or pid. Options are:");
|
||||
pw.println(" --user <USER_ID> | current: When supplying a process name,");
|
||||
pw.println(" specify user of process to profile; uses current user if not");
|
||||
pw.println(" specified.");
|
||||
pw.println(" --clock-type <TYPE>: use the specified clock to report timestamps.");
|
||||
pw.println(" The type can be one of wall | thread-cpu | dual. The default");
|
||||
pw.println(" value is dual.");
|
||||
pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
|
||||
pw.println(" between samples.");
|
||||
pw.println(" --streaming: stream the profiling output to the specified file.");
|
||||
|
||||
@@ -2043,7 +2043,7 @@ public class AppProfiler {
|
||||
}
|
||||
} else if (instr != null && instr.mProfileFile != null) {
|
||||
profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
|
||||
null, false);
|
||||
null, false, 0);
|
||||
}
|
||||
if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
|
||||
// We need to do a debuggable check here. See setAgentApp for why the check is
|
||||
@@ -2053,7 +2053,7 @@ public class AppProfiler {
|
||||
// Do not overwrite already requested agent.
|
||||
if (profilerInfo == null) {
|
||||
profilerInfo = new ProfilerInfo(null, null, 0, false, false,
|
||||
mAppAgentMap.get(processName), true);
|
||||
mAppAgentMap.get(processName), true, 0);
|
||||
} else if (profilerInfo.agent == null) {
|
||||
profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
|
||||
}
|
||||
@@ -2185,7 +2185,9 @@ public class AppProfiler {
|
||||
+ " mAutoStopProfiler="
|
||||
+ mProfileData.getProfilerInfo().autoStopProfiler
|
||||
+ " mStreamingOutput="
|
||||
+ mProfileData.getProfilerInfo().streamingOutput);
|
||||
+ mProfileData.getProfilerInfo().streamingOutput
|
||||
+ " mClockType="
|
||||
+ mProfileData.getProfilerInfo().clockType);
|
||||
pw.println(" mProfileType=" + mProfileType);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user