FileDocCategorySizeDatePackage
SamplingProfilerIntegration.javaAPI DocAndroid 5.1 API8215Thu Mar 12 22:22:10 GMT 2015com.android.internal.os

SamplingProfilerIntegration

public class SamplingProfilerIntegration extends Object
Integrates the framework with Dalvik's sampling profiler.

Fields Summary
private static final String
TAG
public static final String
SNAPSHOT_DIR
private static final boolean
enabled
private static final Executor
snapshotWriter
private static final int
samplingProfilerMilliseconds
private static final int
samplingProfilerDepth
private static final AtomicBoolean
pending
Whether or not a snapshot is being persisted.
private static dalvik.system.profiler.SamplingProfiler
samplingProfiler
private static long
startMillis
Constructors Summary
Methods Summary
private static voidgenerateSnapshotHeader(java.lang.String processName, android.content.pm.PackageInfo packageInfo, java.io.PrintStream out)
generate header for snapshots, with the following format (like an HTTP header but without the \r): Version: \n Process: \n Package: \n Package-Version: \n Build: \n \n

        // profiler version
        out.println("Version: 3");
        out.println("Process: " + processName);
        if (packageInfo != null) {
            out.println("Package: " + packageInfo.packageName);
            out.println("Package-Version: " + packageInfo.versionCode);
        }
        out.println("Build: " + Build.FINGERPRINT);
        // single blank line means the end of snapshot header.
        out.println();
    
public static booleanisEnabled()
Is profiling enabled?

        return enabled;
    
public static voidstart()
Starts the profiler if profiling is enabled.

        if (!enabled) {
            return;
        }
        if (samplingProfiler != null) {
            Log.e(TAG, "SamplingProfilerIntegration already started at " + new Date(startMillis));
            return;
        }

        ThreadGroup group = Thread.currentThread().getThreadGroup();
        SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupThreadSet(group);
        samplingProfiler = new SamplingProfiler(samplingProfilerDepth, threadSet);
        samplingProfiler.start(samplingProfilerMilliseconds);
        startMillis = System.currentTimeMillis();
    
public static voidwriteSnapshot(java.lang.String processName, android.content.pm.PackageInfo packageInfo)
Writes a snapshot if profiling is enabled.

        if (!enabled) {
            return;
        }
        if (samplingProfiler == null) {
            Log.e(TAG, "SamplingProfilerIntegration is not started");
            return;
        }

        /*
         * If we're already writing a snapshot, don't bother enqueueing another
         * request right now. This will reduce the number of individual
         * snapshots and in turn the total amount of memory consumed (one big
         * snapshot is smaller than N subset snapshots).
         */
        if (pending.compareAndSet(false, true)) {
            snapshotWriter.execute(new Runnable() {
                public void run() {
                    try {
                        writeSnapshotFile(processName, packageInfo);
                    } finally {
                        pending.set(false);
                    }
                }
            });
        }
    
private static voidwriteSnapshotFile(java.lang.String processName, android.content.pm.PackageInfo packageInfo)
pass in PackageInfo to retrieve various values for snapshot header

        if (!enabled) {
            return;
        }
        samplingProfiler.stop();

        /*
         * We use the global start time combined with the process name
         * as a unique ID. We can't use a counter because processes
         * restart. This could result in some overlap if we capture
         * two snapshots in rapid succession.
         */
        String name = processName.replaceAll(":", ".");
        String path = SNAPSHOT_DIR + "/" + name + "-" + startMillis + ".snapshot";
        long start = System.currentTimeMillis();
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(path));
            PrintStream out = new PrintStream(outputStream);
            generateSnapshotHeader(name, packageInfo, out);
            if (out.checkError()) {
                throw new IOException();
            }
            BinaryHprofWriter.write(samplingProfiler.getHprofData(), outputStream);
        } catch (IOException e) {
            Log.e(TAG, "Error writing snapshot to " + path, e);
            return;
        } finally {
            IoUtils.closeQuietly(outputStream);
        }
        // set file readable to the world so that SamplingProfilerService
        // can put it to dropbox
        new File(path).setReadable(true, false);

        long elapsed = System.currentTimeMillis() - start;
        Log.i(TAG, "Wrote snapshot " + path + " in " + elapsed + "ms.");
        samplingProfiler.start(samplingProfilerMilliseconds);
    
public static voidwriteZygoteSnapshot()
Writes the zygote's snapshot to internal storage if profiling is enabled.

        if (!enabled) {
            return;
        }
        writeSnapshotFile("zygote", null);
        samplingProfiler.shutdown();
        samplingProfiler = null;
        startMillis = 0;