Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54ccbde9 authored by Mythri Alle's avatar Mythri Alle
Browse files

Extend am profile command to trace long running methods

Extend am profile lowoverhead command to take two more options to trace
long running methods for a specified duration.

Bug: 352518093
Test: tested with am profile lowoverhead start --longrunning
am profile lowoverhead start --longrunning --duration
Flag: com.android.art.flags.always_enable_profile_code

Change-Id: I151d47ada87288141c550af8cf165c3fa6f52e46
parent 382d5af8
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -7224,7 +7224,14 @@ public final class ActivityThread extends ClientTransactionHandler
                        Slog.w(TAG, "Low overhead tracing feature is not enabled");
                        break;
                    }

                    if (profilerInfo.profileLongRunningMethods) {
                        long microToNano = 1000;
                        VMDebug.startLowOverheadTraceForLongRunningMethods(
                                profilerInfo.durationMicros * microToNano);
                    } else {
                        VMDebug.startLowOverheadTraceForAllMethods();
                    }
                    break;
                default:
                    try {
+28 −3
Original line number Diff line number Diff line
@@ -98,9 +98,19 @@ public class ProfilerInfo implements Parcelable {
     */
    public final int profilerOutputVersion;

    /**
     * Indicates if we should trace long running methods for lowoverhead tracing
     */
    public final boolean profileLongRunningMethods;

    /**
     * The duration in microseconds for which the lowoverhed tracing has to be run
     */
    public final long durationMicros;

    public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
            boolean streaming, String agent, boolean attachAgentDuringBind, int clockType,
            int profilerOutputVersion) {
            int profilerOutputVersion, boolean profileLongRunningMethods, long durationMicros) {
        profileFile = filename;
        profileFd = fd;
        samplingInterval = interval;
@@ -110,6 +120,8 @@ public class ProfilerInfo implements Parcelable {
        this.agent = agent;
        this.attachAgentDuringBind = attachAgentDuringBind;
        this.profilerOutputVersion = profilerOutputVersion;
        this.profileLongRunningMethods = profileLongRunningMethods;
        this.durationMicros = durationMicros;
    }

    public ProfilerInfo(ProfilerInfo in) {
@@ -122,6 +134,8 @@ public class ProfilerInfo implements Parcelable {
        attachAgentDuringBind = in.attachAgentDuringBind;
        clockType = in.clockType;
        profilerOutputVersion = in.profilerOutputVersion;
        profileLongRunningMethods = in.profileLongRunningMethods;
        durationMicros = in.durationMicros;
    }

    /**
@@ -165,7 +179,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.clockType, this.profilerOutputVersion);
                this.clockType, this.profilerOutputVersion, this.profileLongRunningMethods,
                this.durationMicros);
    }

    /**
@@ -207,6 +222,8 @@ public class ProfilerInfo implements Parcelable {
        out.writeBoolean(attachAgentDuringBind);
        out.writeInt(clockType);
        out.writeInt(profilerOutputVersion);
        out.writeBoolean(profileLongRunningMethods);
        out.writeLong(durationMicros);
    }

    /** @hide */
@@ -222,6 +239,8 @@ public class ProfilerInfo implements Parcelable {
        proto.write(ProfilerInfoProto.AGENT, agent);
        proto.write(ProfilerInfoProto.CLOCK_TYPE, clockType);
        proto.write(ProfilerInfoProto.PROFILER_OUTPUT_VERSION, profilerOutputVersion);
        proto.write(ProfilerInfoProto.PROFILE_LONG_RUNNING_METHODS, profileLongRunningMethods);
        proto.write(ProfilerInfoProto.DURATION_MICROS, durationMicros);
        proto.end(token);
    }

@@ -248,6 +267,8 @@ public class ProfilerInfo implements Parcelable {
        attachAgentDuringBind = in.readBoolean();
        clockType = in.readInt();
        profilerOutputVersion = in.readInt();
        profileLongRunningMethods = in.readBoolean();
        durationMicros = in.readLong();
    }

    @Override
@@ -265,7 +286,9 @@ public class ProfilerInfo implements Parcelable {
                && samplingInterval == other.samplingInterval
                && streamingOutput == other.streamingOutput && Objects.equals(agent, other.agent)
                && clockType == other.clockType
                && profilerOutputVersion == other.profilerOutputVersion;
                && profilerOutputVersion == other.profilerOutputVersion
                && profileLongRunningMethods == other.profileLongRunningMethods
                && durationMicros == other.durationMicros;
    }

    @Override
@@ -278,6 +301,8 @@ public class ProfilerInfo implements Parcelable {
        result = 31 * result + Objects.hashCode(agent);
        result = 31 * result + clockType;
        result = 31 * result + profilerOutputVersion;
        result = 31 * result + (profileLongRunningMethods ? 1 : 0);
        result = 31 * result + Long.hashCode(durationMicros);
        return result;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ message ProfilerInfoProto {
    // Name of profile output file.
    optional string profile_file = 1;
    optional int32 profile_fd = 2;
    // The sampling interval rate in microseconds.
    optional int32 sampling_interval = 3;
    optional bool auto_stop_profiler = 4;
    optional bool streaming_output = 5;
@@ -37,4 +38,7 @@ message ProfilerInfoProto {
    optional string agent = 6;
    optional int32 clock_type = 7;
    optional int32 profiler_output_version = 8;
    optional bool profile_long_running_methods = 9;
    // Duration in microseconds for which the tracing needs to run.
    optional int64 duration_micros = 10;
}
+4 −2
Original line number Diff line number Diff line
@@ -15916,8 +15916,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                    + android.Manifest.permission.SET_ACTIVITY_WATCHER);
        }
        if (start && profileType == ProfilerInfo.PROFILE_TYPE_REGULAR
                && (profilerInfo == null || profilerInfo.profileFd == null)) {
        if (start
                && (profilerInfo == null
                        || (profileType == ProfilerInfo.PROFILE_TYPE_REGULAR
                                && profilerInfo.profileFd == null))) {
            throw new IllegalArgumentException("null profile info or fd");
        }
+41 −7
Original line number Diff line number Diff line
@@ -209,6 +209,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
    private boolean mAttachAgentDuringBind;  // Whether agent should be attached late.
    private int mClockType; // Whether we need thread cpu / wall clock / both.
    private int mProfilerOutputVersion; // The version of the profiler output.
    private boolean mLongRunningMethods; // Whether we need to trace only long running methods
    private long mDurationMicros; // duration in microseconds that specifies how long to trace.
    private int mDisplayId;
    private int mTaskDisplayAreaFeatureId;
    private int mWindowingMode;
@@ -592,6 +594,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
        mSamplingInterval = 0;
        mAutoStop = false;
        mStreaming = false;
        mLongRunningMethods = false;
        mDurationMicros = 0;
        mUserId = defUser;
        mDisplayId = INVALID_DISPLAY;
        mTaskDisplayAreaFeatureId = FEATURE_UNDEFINED;
@@ -792,9 +796,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
                        return 1;
                    }
                }
                profilerInfo =
                        new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, mStreaming,
                                mAgent, mAttachAgentDuringBind, mClockType, mProfilerOutputVersion);
                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
                        mStreaming, mAgent, mAttachAgentDuringBind, mClockType,
                        mProfilerOutputVersion, mLongRunningMethods, mDurationMicros);
            }

            pw.println("Starting: " + intent);
@@ -1157,6 +1161,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
        mSamplingInterval = 0;
        mStreaming = false;
        mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT;
        mLongRunningMethods = false;
        mDurationMicros = 0;
        mProfilerOutputVersion = ProfilerInfo.OUTPUT_VERSION_DEFAULT;

        String process = null;
@@ -1201,6 +1207,16 @@ final class ActivityManagerShellCommand extends ShellCommand {
            cmd = getNextArgRequired();
            if ("start".equals(cmd)) {
                start = true;
                String opt;
                while ((opt = getNextOption()) != null) {
                    if (opt.equals("--longrunning")) {
                        mLongRunningMethods = true;
                    } else if (opt.equals("--duration")) {
                        // Convert milliseconds to micro seconds
                        long milliToMicro = 1000;
                        mDurationMicros = Long.parseLong(getNextArgRequired()) * milliToMicro;
                    }
                }
            } else if ("stop".equals(cmd)) {
                start = false;
            } else {
@@ -1229,16 +1245,21 @@ final class ActivityManagerShellCommand extends ShellCommand {
        // For regular method tracing  profileFile should be provided with the start command. For
        // low overhead method tracing the profileFile is optional and provided with the stop
        // command.
        if ((start && profileType == ProfilerInfo.PROFILE_TYPE_REGULAR)
                || (profileType == ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD
                  && !start && getRemainingArgsCount() > 0)) {
        boolean hasFileArg = (profileType == ProfilerInfo.PROFILE_TYPE_REGULAR && start)
                || (profileType == ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD && !start
                        && getRemainingArgsCount() > 0);
        if (hasFileArg) {
            profileFile = getNextArgRequired();
            fd = openFileForSystem(profileFile, "w");
            if (fd == null) {
                return -1;
            }
        }

        if (start || hasFileArg) {
            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
                    null, false, mClockType, mProfilerOutputVersion);
                    null, false, mClockType, mProfilerOutputVersion, mLongRunningMethods,
                    mDurationMicros);
        }

        if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
@@ -4527,6 +4548,19 @@ final class ActivityManagerShellCommand extends ShellCommand {
            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("  profile lowoverhead start [--longrunning --duration DURATION] <PROCESS>");
            pw.println("      Starts a lowoverhead trace on a process. The given <PROCESS>");
            pw.println("        argument may be either a process name or pid.  Options are:");
            pw.println("      --longrunning: Traces methods that run longer than a specific");
            pw.println("          threshold. This threshold is a build-time constant");
            pw.println("      --duration DURATION: trace for the specified DURATION milliseconds.");
            pw.println("          This argument only applies for long running traces. A default");
            pw.println("          value is used when duration is not specified.");
            pw.println("  profile lowoverhead stop <PROCESS> [<FILE>]");
            pw.println("      Stops an ongoing lowoverhead trace on a process. The given");
            pw.println("        <PROCESS> argument may be either a process name or pid.");
            pw.println("        An optional <FILE> argument may be provided to dump the");
            pw.println("        collected trace");
            pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] [-b <format>] ");
            pw.println("           <PROCESS> <FILE>");
            pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
Loading