summaryrefslogtreecommitdiffstats
path: root/tools/preload/MemoryUsage.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
commit9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch)
treed88beb88001f2482911e3d28e43833b50e4b4e97 /tools/preload/MemoryUsage.java
parentd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff)
downloadframeworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'tools/preload/MemoryUsage.java')
-rw-r--r--tools/preload/MemoryUsage.java283
1 files changed, 283 insertions, 0 deletions
diff --git a/tools/preload/MemoryUsage.java b/tools/preload/MemoryUsage.java
new file mode 100644
index 0000000..e5dfb2a
--- /dev/null
+++ b/tools/preload/MemoryUsage.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Memory usage information.
+ */
+class MemoryUsage implements Serializable {
+
+ private static final long serialVersionUID = 0;
+
+ static final MemoryUsage NOT_AVAILABLE = new MemoryUsage();
+
+ static int errorCount = 0;
+ static final int MAXIMUM_ERRORS = 10; // give up after this many fails
+
+ final int nativeSharedPages;
+ final int javaSharedPages;
+ final int otherSharedPages;
+ final int nativePrivatePages;
+ final int javaPrivatePages;
+ final int otherPrivatePages;
+
+ final int allocCount;
+ final int allocSize;
+ final int freedCount;
+ final int freedSize;
+ final long nativeHeapSize;
+
+ public MemoryUsage(String line) {
+ String[] parsed = line.split(",");
+
+ nativeSharedPages = Integer.parseInt(parsed[1]);
+ javaSharedPages = Integer.parseInt(parsed[2]);
+ otherSharedPages = Integer.parseInt(parsed[3]);
+ nativePrivatePages = Integer.parseInt(parsed[4]);
+ javaPrivatePages = Integer.parseInt(parsed[5]);
+ otherPrivatePages = Integer.parseInt(parsed[6]);
+ allocCount = Integer.parseInt(parsed[7]);
+ allocSize = Integer.parseInt(parsed[8]);
+ freedCount = Integer.parseInt(parsed[9]);
+ freedSize = Integer.parseInt(parsed[10]);
+ nativeHeapSize = Long.parseLong(parsed[11]);
+ }
+
+ MemoryUsage() {
+ nativeSharedPages = -1;
+ javaSharedPages = -1;
+ otherSharedPages = -1;
+ nativePrivatePages = -1;
+ javaPrivatePages = -1;
+ otherPrivatePages = -1;
+
+ allocCount = -1;
+ allocSize = -1;
+ freedCount = -1;
+ freedSize = -1;
+ nativeHeapSize = -1;
+ }
+
+ MemoryUsage(int nativeSharedPages,
+ int javaSharedPages,
+ int otherSharedPages,
+ int nativePrivatePages,
+ int javaPrivatePages,
+ int otherPrivatePages,
+ int allocCount,
+ int allocSize,
+ int freedCount,
+ int freedSize,
+ long nativeHeapSize) {
+ this.nativeSharedPages = nativeSharedPages;
+ this.javaSharedPages = javaSharedPages;
+ this.otherSharedPages = otherSharedPages;
+ this.nativePrivatePages = nativePrivatePages;
+ this.javaPrivatePages = javaPrivatePages;
+ this.otherPrivatePages = otherPrivatePages;
+ this.allocCount = allocCount;
+ this.allocSize = allocSize;
+ this.freedCount = freedCount;
+ this.freedSize = freedSize;
+ this.nativeHeapSize = nativeHeapSize;
+ }
+
+ MemoryUsage subtract(MemoryUsage baseline) {
+ return new MemoryUsage(
+ nativeSharedPages - baseline.nativeSharedPages,
+ javaSharedPages - baseline.javaSharedPages,
+ otherSharedPages - baseline.otherSharedPages,
+ nativePrivatePages - baseline.nativePrivatePages,
+ javaPrivatePages - baseline.javaPrivatePages,
+ otherPrivatePages - baseline.otherPrivatePages,
+ allocCount - baseline.allocCount,
+ allocSize - baseline.allocSize,
+ freedCount - baseline.freedCount,
+ freedSize - baseline.freedSize,
+ nativeHeapSize - baseline.nativeHeapSize);
+ }
+
+ int javaHeapSize() {
+ return allocSize - freedSize;
+ }
+
+ int javaPagesInK() {
+ return (javaSharedPages + javaPrivatePages) * 4;
+ }
+
+ int nativePagesInK() {
+ return (nativeSharedPages + nativePrivatePages) * 4;
+ }
+ int otherPagesInK() {
+ return (otherSharedPages + otherPrivatePages) * 4;
+ }
+
+ /**
+ * Was this information available?
+ */
+ boolean isAvailable() {
+ return nativeSharedPages != -1;
+ }
+
+ /**
+ * Measures baseline memory usage.
+ */
+ static MemoryUsage baseline() {
+ return forClass(null);
+ }
+
+ private static final String CLASS_PATH = "-Xbootclasspath"
+ + ":/system/framework/core.jar"
+ + ":/system/framework/ext.jar"
+ + ":/system/framework/framework.jar"
+ + ":/system/framework/framework-tests.jar"
+ + ":/system/framework/services.jar"
+ + ":/system/framework/loadclass.jar";
+
+ private static final String[] GET_DIRTY_PAGES = {
+ "adb", "-e", "shell", "dalvikvm", CLASS_PATH, "LoadClass" };
+
+ /**
+ * Measures memory usage for the given class.
+ */
+ static MemoryUsage forClass(String className) {
+
+ // This is a coarse approximation for determining that no device is connected,
+ // or that the communication protocol has changed, but we'll keep going and stop whining.
+ if (errorCount >= MAXIMUM_ERRORS) {
+ return NOT_AVAILABLE;
+ }
+
+ MeasureWithTimeout measurer = new MeasureWithTimeout(className);
+
+ new Thread(measurer).start();
+
+ synchronized (measurer) {
+ if (measurer.memoryUsage == null) {
+ // Wait up to 10s.
+ try {
+ measurer.wait(30000);
+ } catch (InterruptedException e) {
+ System.err.println("Interrupted waiting for measurement.");
+ e.printStackTrace();
+ return NOT_AVAILABLE;
+ }
+
+ // If it's still null.
+ if (measurer.memoryUsage == null) {
+ System.err.println("Timed out while measuring "
+ + className + ".");
+ return NOT_AVAILABLE;
+ }
+ }
+
+ System.err.println("Got memory usage for " + className + ".");
+ return measurer.memoryUsage;
+ }
+ }
+
+ static class MeasureWithTimeout implements Runnable {
+
+ final String className;
+ MemoryUsage memoryUsage = null;
+
+ MeasureWithTimeout(String className) {
+ this.className = className;
+ }
+
+ public void run() {
+ MemoryUsage measured = measure();
+
+ synchronized (this) {
+ memoryUsage = measured;
+ notifyAll();
+ }
+ }
+
+ private MemoryUsage measure() {
+ String[] commands = GET_DIRTY_PAGES;
+ if (className != null) {
+ List<String> commandList = new ArrayList<String>(
+ GET_DIRTY_PAGES.length + 1);
+ commandList.addAll(Arrays.asList(commands));
+ commandList.add(className);
+ commands = commandList.toArray(new String[commandList.size()]);
+ }
+
+ try {
+ final Process process = Runtime.getRuntime().exec(commands);
+
+ final InputStream err = process.getErrorStream();
+
+ // Send error output to stderr.
+ Thread errThread = new Thread() {
+ @Override
+ public void run() {
+ copy(err, System.err);
+ }
+ };
+ errThread.setDaemon(true);
+ errThread.start();
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(process.getInputStream()));
+ String line = in.readLine();
+ if (line == null || !line.startsWith("DECAFBAD,")) {
+ System.err.println("Got bad response for " + className
+ + ": " + line);
+ errorCount += 1;
+ return NOT_AVAILABLE;
+ }
+
+ in.close();
+ err.close();
+ process.destroy();
+
+ return new MemoryUsage(line);
+ } catch (IOException e) {
+ System.err.println("Error getting stats for "
+ + className + ".");
+ e.printStackTrace();
+ return NOT_AVAILABLE;
+ }
+ }
+
+ }
+
+ /**
+ * Copies from one stream to another.
+ */
+ private static void copy(InputStream in, OutputStream out) {
+ byte[] buffer = new byte[1024];
+ int read;
+ try {
+ while ((read = in.read(buffer)) > -1) {
+ out.write(buffer, 0, read);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}