SamplingProfilerIntegration.java revision e540833fdff4d58e37c9ba859388e24e2945ed45
1package com.android.internal.os;
2
3import dalvik.system.SamplingProfiler;
4
5import java.io.File;
6import java.io.FileOutputStream;
7import java.io.IOException;
8import java.io.FileNotFoundException;
9import java.util.concurrent.Executor;
10import java.util.concurrent.Executors;
11
12import android.util.Log;
13import android.os.*;
14import android.net.Uri;
15
16/**
17 * Integrates the framework with Dalvik's sampling profiler.
18 */
19public class SamplingProfilerIntegration {
20
21    private static final String TAG = "SamplingProfilerIntegration";
22
23    private static final boolean enabled;
24    private static final Executor snapshotWriter;
25    static {
26        enabled = "1".equals(SystemProperties.get("persist.sampling_profiler"));
27        if (enabled) {
28            snapshotWriter = Executors.newSingleThreadExecutor();
29            Log.i(TAG, "Profiler is enabled.");
30        } else {
31            snapshotWriter = null;
32            Log.i(TAG, "Profiler is disabled.");
33        }
34    }
35
36    /**
37     * Is profiling enabled?
38     */
39    public static boolean isEnabled() {
40        return enabled;
41    }
42
43    /**
44     * Starts the profiler if profiling is enabled.
45     */
46    public static void start() {
47        if (!enabled) return;
48        SamplingProfiler.getInstance().start(10);
49    }
50
51    /** Whether or not we've created the snapshots dir. */
52    static boolean dirMade = false;
53
54    /** Whether or not a snapshot is being persisted. */
55    static volatile boolean pending;
56
57    /**
58     * Writes a snapshot to the SD card if profiling is enabled.
59     */
60    public static void writeSnapshot(final String name) {
61        if (!enabled) return;
62
63        if (!pending) {
64            pending = true;
65            snapshotWriter.execute(new Runnable() {
66                public void run() {
67                    String dir = "/sdcard/snapshots";
68                    if (!dirMade) {
69                        makeDirectory(dir);
70                        dirMade = true;
71                    }
72                    try {
73                        writeSnapshot(dir, name);
74                    } finally {
75                        pending = false;
76                    }
77                }
78            });
79        }
80    }
81
82    /**
83     * Writes the zygote's snapshot to internal storage if profiling is enabled.
84     */
85    public static void writeZygoteSnapshot() {
86        if (!enabled) return;
87
88        String dir = "/data/zygote/snapshots";
89        makeDirectory(dir);
90        writeSnapshot(dir, "zygote");
91    }
92
93    private static void writeSnapshot(String dir, String name) {
94        byte[] snapshot = SamplingProfiler.getInstance().snapshot();
95        if (snapshot == null) {
96            return;
97        }
98
99        /*
100         * We use the current time as a unique ID. We can't use a counter
101         * because processes restart. This could result in some overlap if
102         * we capture two snapshots in rapid succession.
103         */
104        long start = System.currentTimeMillis();
105        String path = dir + "/" + name.replace(':', '.') + "-"
106                + System.currentTimeMillis() + ".snapshot";
107        try {
108            // Try to open the file a few times. The SD card may not be mounted.
109            FileOutputStream out;
110            int count = 0;
111            while (true) {
112                try {
113                    out = new FileOutputStream(path);
114                    break;
115                } catch (FileNotFoundException e) {
116                    if (++count > 3) {
117                        Log.e(TAG, "Could not open " + path + ".");
118                        return;
119                    }
120
121                    // Sleep for a bit and then try again.
122                    try {
123                        Thread.sleep(2500);
124                    } catch (InterruptedException e1) { /* ignore */ }
125                }
126            }
127
128            try {
129                out.write(snapshot);
130            } finally {
131                out.close();
132            }
133            long elapsed = System.currentTimeMillis() - start;
134            Log.i(TAG, "Wrote snapshot for " + name
135                    + " in " + elapsed + "ms.");
136        } catch (IOException e) {
137            Log.e(TAG, "Error writing snapshot.", e);
138        }
139    }
140
141    private static void makeDirectory(String dir) {
142        new File(dir).mkdirs();
143    }
144}
145