From bb44e42de93e2e02d4314ffdee4cbc4d0df7ecc2 Mon Sep 17 00:00:00 2001 From: Shukang Zhou Date: Tue, 24 Jan 2017 15:30:29 -0800 Subject: [PATCH] [Frameworks] Add an 'am' cmd option to enable streaming in profiling. Add option '--streaming' to 'am start' and 'am profile' commands. If the option is given, the output of method trace profiling will be streamed into the specified file, so the output is no longer limited by the buffer size. Test: m -j48 test-art-host; m -j48 ART_TEST_TRACE=true ART_TEST_TRACE_STREAM=true test-art-host; I also tested manually. Tried all 8 combinations of sampling/instrumention streaming/non-streaming 'am start --start-profiler' / 'am profile start' The output files are all in expected shape. Bug: 33300765 Merged-In: I8a5136a1c7330c8260b7c6c8da63f42a73aee275 Change-Id: I8a5136a1c7330c8260b7c6c8da63f42a73aee275 --- cmds/am/src/com/android/commands/am/Am.java | 22 +++++++++++++++---- core/java/android/app/ActivityThread.java | 6 ++++- core/java/android/app/ProfilerInfo.java | 9 +++++++- core/java/android/os/Debug.java | 4 ++-- .../server/am/ActivityManagerService.java | 10 +++++++-- .../server/am/ActivityStackSupervisor.java | 3 ++- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index d959f5c3bb3f4..4e1b6db71f306 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -110,6 +110,7 @@ public class Am extends BaseCommand { private String mProfileFile; private int mSamplingInterval; private boolean mAutoStop; + private boolean mStreaming; // Streaming the profiling output to a file. private int mStackId; /** @@ -127,7 +128,7 @@ public class Am extends BaseCommand { pw.println( "usage: am [subcommand] [options]\n" + "usage: am start [-D] [-N] [-W] [-P ] [--start-profiler ]\n" + - " [--sampling INTERVAL] [-R COUNT] [-S]\n" + + " [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]\n" + " [--track-allocation] [--user | current] \n" + " am startservice [--user | current] \n" + " am stopservice [--user | current] \n" + @@ -138,7 +139,8 @@ public class Am extends BaseCommand { " am instrument [-r] [-e ] [-p ] [-w]\n" + " [--user | current]\n" + " [--no-window-animation] [--abi ] \n" + - " am profile start [--user current] [--sampling INTERVAL] \n" + + " am profile start [--user current] [--sampling INTERVAL]\n"+ + " [--streaming] \n" + " am profile stop [--user current] []\n" + " am dumpheap [--user current] [-n] \n" + " am set-debug-app [-w] [--persistent] \n" + @@ -191,6 +193,8 @@ public class Am extends BaseCommand { " --start-profiler : start profiler and send results to \n" + " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" + " between samples (use with --start-profiler)\n" + + " --streaming: stream the profiling output to the specified file (use\n" + + " with --start-profiler)\n" + " -P : like above, but profiling stops when app goes idle\n" + " -R: repeat the activity launch times. Prior to each repeat,\n" + " the top activity will be finished.\n" + @@ -250,6 +254,9 @@ public class Am extends BaseCommand { " may be either a process name or pid. Options are:\n" + " --user | current: When supplying a process name,\n" + " specify user of process to profile; uses current user if not specified.\n" + + " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" + + " between samples\n" + + " --streaming: stream the profiling output to the specified file\n" + "\n" + "am dumpheap: dump the heap of a process. The given argument may\n" + " be either a process name or pid. Options are:\n" + @@ -484,6 +491,7 @@ public class Am extends BaseCommand { mProfileFile = null; mSamplingInterval = 0; mAutoStop = false; + mStreaming = false; mUserId = defUser; mStackId = INVALID_STACK_ID; @@ -504,6 +512,8 @@ public class Am extends BaseCommand { mAutoStop = false; } else if (opt.equals("--sampling")) { mSamplingInterval = Integer.parseInt(nextArgRequired()); + } else if (opt.equals("--streaming")) { + mStreaming = true; } else if (opt.equals("-R")) { mRepeat = Integer.parseInt(nextArgRequired()); } else if (opt.equals("-S")) { @@ -616,7 +626,8 @@ public class Am extends BaseCommand { System.err.println("Consider using a file under /data/local/tmp/"); return; } - profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop); + profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, + mStreaming); } IActivityManager.WaitResult result = null; @@ -974,6 +985,7 @@ public class Am extends BaseCommand { int userId = UserHandle.USER_CURRENT; int profileType = 0; mSamplingInterval = 0; + mStreaming = false; String process = null; @@ -987,6 +999,8 @@ public class Am extends BaseCommand { userId = parseUserArg(nextArgRequired()); } else if (opt.equals("--wall")) { wall = true; + } else if (opt.equals("--streaming")) { + mStreaming = true; } else if (opt.equals("--sampling")) { mSamplingInterval = Integer.parseInt(nextArgRequired()); } else { @@ -1038,7 +1052,7 @@ public class Am extends BaseCommand { System.err.println("Consider using a file under /data/local/tmp/"); return; } - profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false); + profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming); } try { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9d2ef91473887..18b7e24a01720 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -535,6 +535,7 @@ public final class ActivityThread { ParcelFileDescriptor profileFd; int samplingInterval; boolean autoStopProfiler; + boolean streamingOutput; boolean profiling; boolean handlingProfiling; public void setProfiler(ProfilerInfo profilerInfo) { @@ -560,6 +561,7 @@ public final class ActivityThread { profileFd = fd; samplingInterval = profilerInfo.samplingInterval; autoStopProfiler = profilerInfo.autoStopProfiler; + streamingOutput = profilerInfo.streamingOutput; } public void startProfiling() { if (profileFd == null || profiling) { @@ -568,7 +570,8 @@ public final class ActivityThread { try { int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8); VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), - bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval); + bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval, + streamingOutput); profiling = true; } catch (RuntimeException e) { Slog.w(TAG, "Profiling failed on path " + profileFile); @@ -5111,6 +5114,7 @@ public final class ActivityThread { mProfiler.profileFd = data.initProfilerInfo.profileFd; mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; + mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput; } // send up app name; do this *before* waiting for debugger diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java index cea7c3cbe8c3f..f3fe6778375bc 100644 --- a/core/java/android/app/ProfilerInfo.java +++ b/core/java/android/app/ProfilerInfo.java @@ -39,11 +39,16 @@ public class ProfilerInfo implements Parcelable { /* Automatically stop the profiler when the app goes idle. */ public final boolean autoStopProfiler; - public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop) { + /* Indicates whether to stream the profiling info to the out file continuously. */ + public final boolean streamingOutput; + + public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, + boolean streaming) { profileFile = filename; profileFd = fd; samplingInterval = interval; autoStopProfiler = autoStop; + streamingOutput = streaming; } public int describeContents() { @@ -64,6 +69,7 @@ public class ProfilerInfo implements Parcelable { } out.writeInt(samplingInterval); out.writeInt(autoStopProfiler ? 1 : 0); + out.writeInt(streamingOutput ? 1 : 0); } public static final Parcelable.Creator CREATOR = @@ -82,5 +88,6 @@ public class ProfilerInfo implements Parcelable { profileFd = in.readInt() != 0 ? ParcelFileDescriptor.CREATOR.createFromParcel(in) : null; samplingInterval = in.readInt(); autoStopProfiler = in.readInt() != 0; + streamingOutput = in.readInt() != 0; } } diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 175d883da29de..210ddb6cd3970 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -1119,8 +1119,8 @@ public final class Debug * @hide */ public static void startMethodTracing(String traceName, FileDescriptor fd, - int bufferSize, int flags) { - VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0); + int bufferSize, int flags, boolean streamOutput) { + VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0, streamOutput); } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 64c8d95edd19e..fb8ae35ca6416 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1391,6 +1391,7 @@ public final class ActivityManagerService extends ActivityManagerNative ParcelFileDescriptor mProfileFd; int mSamplingInterval = 0; boolean mAutoStopProfiler = false; + boolean mStreamingOutput = false; int mProfileType = 0; final ProcessMap> mMemWatchProcesses = new ProcessMap<>(); String mMemWatchDumpProcName; @@ -6587,12 +6588,14 @@ public final class ActivityManagerService extends ActivityManagerNative ParcelFileDescriptor profileFd = null; int samplingInterval = 0; boolean profileAutoStop = false; + boolean profileStreamingOutput = false; if (mProfileApp != null && mProfileApp.equals(processName)) { mProfileProc = app; profileFile = mProfileFile; profileFd = mProfileFd; samplingInterval = mSamplingInterval; profileAutoStop = mAutoStopProfiler; + profileStreamingOutput = mStreamingOutput; } boolean enableTrackAllocation = false; if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) { @@ -6622,7 +6625,8 @@ public final class ActivityManagerService extends ActivityManagerNative profileFd = profileFd.dup(); } ProfilerInfo profilerInfo = profileFile == null ? null - : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop); + : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop, + profileStreamingOutput); checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, @@ -12108,6 +12112,7 @@ public final class ActivityManagerService extends ActivityManagerNative mProfileFd = profilerInfo.profileFd; mSamplingInterval = profilerInfo.samplingInterval; mAutoStopProfiler = profilerInfo.autoStopProfiler; + mStreamingOutput = profilerInfo.streamingOutput; mProfileType = 0; } } @@ -14992,7 +14997,7 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc); pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd); pw.println(" mSamplingInterval=" + mSamplingInterval + " mAutoStopProfiler=" - + mAutoStopProfiler); + + mAutoStopProfiler + " mStreamingOutput=" + mStreamingOutput); pw.println(" mProfileType=" + mProfileType); } } @@ -21511,6 +21516,7 @@ public final class ActivityManagerService extends ActivityManagerNative mProfileFile = null; mProfileType = 0; mAutoStopProfiler = false; + mStreamingOutput = false; mSamplingInterval = 0; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c6ab9186456d8..2262697e34618 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1296,7 +1296,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } profilerInfo = new ProfilerInfo(profileFile, profileFd, - mService.mSamplingInterval, mService.mAutoStopProfiler); + mService.mSamplingInterval, mService.mAutoStopProfiler, + mService.mStreamingOutput); } } }