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

Commit 6863c10b authored by Mythri Alle's avatar Mythri Alle
Browse files

Add a flag to choose the output format for the am profile command

ART now supports a new method trace format that allows us to do more
optimizations to improve both performance and to reduce the size of the
generated trace files. Since the new format won't work with existing
parsers we add a flag so the users could choose which format they need.

Bug: 259258187
Test: am profile start --profiler-output-format 1 / 2
am start-activity --start-profiler --profiler-output-version 1 / 2
am start-activity --streaming --start-profiler --profiler-output-version 1 / 2
am profile start --streaming --profiler-output-format 1 / 2

Change-Id: Ifbcf34f717aaa53fd13adb06e2dfbcfff133bf2c
parent 9138e506
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -968,6 +968,7 @@ public final class ActivityThread extends ClientTransactionHandler
        boolean autoStopProfiler;
        boolean streamingOutput;
        int mClockType;
        int mProfilerOutputVersion;
        boolean profiling;
        boolean handlingProfiling;
        public void setProfiler(ProfilerInfo profilerInfo) {
@@ -995,6 +996,7 @@ public final class ActivityThread extends ClientTransactionHandler
            autoStopProfiler = profilerInfo.autoStopProfiler;
            streamingOutput = profilerInfo.streamingOutput;
            mClockType = profilerInfo.clockType;
            mProfilerOutputVersion = profilerInfo.profilerOutputVersion;
        }
        public void startProfiling() {
            if (profileFd == null || profiling) {
@@ -1002,9 +1004,11 @@ public final class ActivityThread extends ClientTransactionHandler
            }
            try {
                int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
                int flags = 0;
                flags = mClockType | ProfilerInfo.getFlagsForOutputVersion(mProfilerOutputVersion);
                VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
                        bufferSize * 1024 * 1024, mClockType, samplingInterval != 0,
                        samplingInterval, streamingOutput);
                        bufferSize * 1024 * 1024, flags, samplingInterval != 0, samplingInterval,
                        streamingOutput);
                profiling = true;
            } catch (RuntimeException e) {
                Slog.w(TAG, "Profiling failed on path " + profileFile, e);
@@ -7043,6 +7047,7 @@ public final class ActivityThread extends ClientTransactionHandler
            mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
            mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
            mProfiler.mClockType = data.initProfilerInfo.clockType;
            mProfiler.mProfilerOutputVersion = data.initProfilerInfo.profilerOutputVersion;
            if (data.initProfilerInfo.attachAgentDuringBind) {
                agent = data.initProfilerInfo.agent;
            }
+38 −6
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ import java.util.Objects;
 * {@hide}
 */
public class ProfilerInfo implements Parcelable {

    // Version of the profiler output
    public static final int OUTPUT_VERSION_DEFAULT = 1;
    // 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;
@@ -43,6 +44,9 @@ public class ProfilerInfo implements Parcelable {
    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;
    // The second and third bits of the flags field specify the trace format version. This should
    // match with kTraceFormatVersionShift defined in art/runtime/trace.h.
    public static final int TRACE_FORMAT_VERSION_SHIFT = 1;

    private static final String TAG = "ProfilerInfo";

@@ -83,8 +87,14 @@ public class ProfilerInfo implements Parcelable {
     */
    public final int clockType;

    /**
     * Indicates the version of profiler output.
     */
    public final int profilerOutputVersion;

    public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
            boolean streaming, String agent, boolean attachAgentDuringBind, int clockType) {
            boolean streaming, String agent, boolean attachAgentDuringBind, int clockType,
            int profilerOutputVersion) {
        profileFile = filename;
        profileFd = fd;
        samplingInterval = interval;
@@ -93,6 +103,7 @@ public class ProfilerInfo implements Parcelable {
        this.clockType = clockType;
        this.agent = agent;
        this.attachAgentDuringBind = attachAgentDuringBind;
        this.profilerOutputVersion = profilerOutputVersion;
    }

    public ProfilerInfo(ProfilerInfo in) {
@@ -104,6 +115,7 @@ public class ProfilerInfo implements Parcelable {
        agent = in.agent;
        attachAgentDuringBind = in.attachAgentDuringBind;
        clockType = in.clockType;
        profilerOutputVersion = in.profilerOutputVersion;
    }

    /**
@@ -124,6 +136,22 @@ public class ProfilerInfo implements Parcelable {
        }
    }

    /**
     * Get the flags that need to be passed to VMDebug.startMethodTracing to specify the desired
     * output format.
     */
    public static int getFlagsForOutputVersion(int version) {
        // Only two version 1 and version 2 are supported. Just use the default if we see an unknown
        // version.
        if (version != 1 || version != 2) {
            version = OUTPUT_VERSION_DEFAULT;
        }

        // The encoded version in the flags starts from 0, where as the version that we read from
        // user starts from 1. So, subtract one before encoding it in the flags.
        return (version - 1) << TRACE_FORMAT_VERSION_SHIFT;
    }

    /**
     * Return a new ProfilerInfo instance, with fields populated from this object,
     * and {@link agent} and {@link attachAgentDuringBind} as given.
@@ -131,7 +159,7 @@ 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.clockType, this.profilerOutputVersion);
    }

    /**
@@ -172,6 +200,7 @@ public class ProfilerInfo implements Parcelable {
        out.writeString(agent);
        out.writeBoolean(attachAgentDuringBind);
        out.writeInt(clockType);
        out.writeInt(profilerOutputVersion);
    }

    /** @hide */
@@ -186,6 +215,7 @@ public class ProfilerInfo implements Parcelable {
        proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput);
        proto.write(ProfilerInfoProto.AGENT, agent);
        proto.write(ProfilerInfoProto.CLOCK_TYPE, clockType);
        proto.write(ProfilerInfoProto.PROFILER_OUTPUT_VERSION, profilerOutputVersion);
        proto.end(token);
    }

@@ -211,6 +241,7 @@ public class ProfilerInfo implements Parcelable {
        agent = in.readString();
        attachAgentDuringBind = in.readBoolean();
        clockType = in.readInt();
        profilerOutputVersion = in.readInt();
    }

    @Override
@@ -226,9 +257,9 @@ public class ProfilerInfo implements Parcelable {
        return Objects.equals(profileFile, other.profileFile)
                && autoStopProfiler == other.autoStopProfiler
                && samplingInterval == other.samplingInterval
                && streamingOutput == other.streamingOutput
                && Objects.equals(agent, other.agent)
                && clockType == other.clockType;
                && streamingOutput == other.streamingOutput && Objects.equals(agent, other.agent)
                && clockType == other.clockType
                && profilerOutputVersion == other.profilerOutputVersion;
    }

    @Override
@@ -240,6 +271,7 @@ public class ProfilerInfo implements Parcelable {
        result = 31 * result + (streamingOutput ? 1 : 0);
        result = 31 * result + Objects.hashCode(agent);
        result = 31 * result + clockType;
        result = 31 * result + profilerOutputVersion;
        return result;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -36,4 +36,5 @@ message ProfilerInfoProto {
    // Denotes an agent (and its parameters) to attach for profiling.
    optional string agent = 6;
    optional int32 clock_type = 7;
    optional int32 profiler_output_version = 8;
}
+19 −4
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
    private static final DateTimeFormatter LOG_NAME_TIME_FORMATTER =
            DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss", Locale.ROOT);

    private static final String PROFILER_OUTPUT_VERSION_FLAG = "--profiler-output-version";

    // IPC interface to activity manager -- don't need to do additional security checks.
    final IActivityManager mInterface;
    final IActivityTaskManager mTaskInterface;
@@ -195,6 +197,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
    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 mProfilerOutputVersion; // The version of the profiler output.
    private int mDisplayId;
    private int mTaskDisplayAreaFeatureId;
    private int mWindowingMode;
@@ -501,6 +504,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
                } else if (opt.equals("--clock-type")) {
                    String clock_type = getNextArgRequired();
                    mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
                } else if (opt.equals(PROFILER_OUTPUT_VERSION_FLAG)) {
                    mProfilerOutputVersion = Integer.parseInt(getNextArgRequired());
                } else if (opt.equals("--streaming")) {
                    mStreaming = true;
                } else if (opt.equals("--attach-agent")) {
@@ -659,8 +664,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
                        return 1;
                    }
                }
                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
                        mStreaming, mAgent, mAttachAgentDuringBind, mClockType);
                profilerInfo =
                        new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, mStreaming,
                                mAgent, mAttachAgentDuringBind, mClockType, mProfilerOutputVersion);
            }

            pw.println("Starting: " + intent);
@@ -1003,6 +1009,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
        mSamplingInterval = 0;
        mStreaming = false;
        mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT;
        mProfilerOutputVersion = ProfilerInfo.OUTPUT_VERSION_DEFAULT;

        String process = null;

@@ -1017,6 +1024,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
                } else if (opt.equals("--clock-type")) {
                    String clock_type = getNextArgRequired();
                    mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
                } else if (opt.equals(PROFILER_OUTPUT_VERSION_FLAG)) {
                    mProfilerOutputVersion = Integer.parseInt(getNextArgRequired());
                } else if (opt.equals("--streaming")) {
                    mStreaming = true;
                } else if (opt.equals("--sampling")) {
@@ -1064,7 +1073,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
                return -1;
            }
            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
                    null, false, mClockType);
                    null, false, mClockType, mProfilerOutputVersion);
        }

        if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
@@ -4146,6 +4155,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("      Print this help text.");
            pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
            pw.println("          [--sampling INTERVAL] [--clock-type <TYPE>] [--streaming]");
            pw.println("          [" + PROFILER_OUTPUT_VERSION_FLAG + " NUMBER]");
            pw.println("          [-R COUNT] [-S] [--track-allocation]");
            pw.println("          [--user <USER_ID> | current] [--suspend] <INTENT>");
            pw.println("      Start an Activity.  Options are:");
@@ -4161,6 +4171,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
            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("      " + PROFILER_OUTPUT_VERSION_FLAG + " Specify the version of the");
            pw.println("          profiling output (use with --start-profiler)");
            pw.println("      -P <FILE>: like above, but profiling stops when app goes idle");
            pw.println("      --attach-agent <agent>: attach the given agent before binding");
            pw.println("      --attach-agent-bind <agent>: attach the given agent during binding");
@@ -4252,6 +4264,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
            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("          [" + PROFILER_OUTPUT_VERSION_FLAG + " VERSION]");
            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:");
@@ -4261,6 +4274,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
            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("      " + PROFILER_OUTPUT_VERSION_FLAG + "VERSION: specifies the output");
            pw.println("          format version");
            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.");
+9 −6
Original line number Diff line number Diff line
@@ -2482,8 +2482,8 @@ public class AppProfiler {
                    }
                }
            } else if (instr != null && instr.mProfileFile != null) {
                profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
                        null, false, 0);
                profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false, null,
                        false, 0, ProfilerInfo.OUTPUT_VERSION_DEFAULT);
            }
            if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
                // We need to do a debuggable check here. See setAgentApp for why the check is
@@ -2493,7 +2493,8 @@ public class AppProfiler {
                    // Do not overwrite already requested agent.
                    if (profilerInfo == null) {
                        profilerInfo = new ProfilerInfo(null, null, 0, false, false,
                                mAppAgentMap.get(processName), true, 0);
                                mAppAgentMap.get(processName), true, 0,
                                ProfilerInfo.OUTPUT_VERSION_DEFAULT);
                    } else if (profilerInfo.agent == null) {
                        profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
                    }
@@ -2620,14 +2621,16 @@ public class AppProfiler {
                if (mProfileData.getProfilerInfo() != null) {
                    pw.println("  mProfileFile=" + mProfileData.getProfilerInfo().profileFile
                            + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
                    pw.println("  mSamplingInterval="
                            + mProfileData.getProfilerInfo().samplingInterval
                    pw.println(
                            "  mSamplingInterval=" + mProfileData.getProfilerInfo().samplingInterval
                            + " mAutoStopProfiler="
                            + mProfileData.getProfilerInfo().autoStopProfiler
                            + " mStreamingOutput="
                            + mProfileData.getProfilerInfo().streamingOutput
                            + " mClockType="
                            + mProfileData.getProfilerInfo().clockType);
                            + mProfileData.getProfilerInfo().clockType
                            + " mProfilerOutputVersion="
                            + mProfileData.getProfilerInfo().profilerOutputVersion);
                    pw.println("  mProfileType=" + mProfileType);
                }
            }