summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2011-03-28 00:12:36 -0700
committerBrian Carlstrom <bdc@google.com>2011-03-29 17:14:55 -0700
commit6b1f9f877b70fcc5375fa33a445ac84777757eb2 (patch)
treea1fd672e954402093822130ace532090b0fab543
parent4624f350313daaae52068c5d1d12b88859d43e54 (diff)
downloadandroid_dalvik-6b1f9f877b70fcc5375fa33a445ac84777757eb2.tar.gz
android_dalvik-6b1f9f877b70fcc5375fa33a445ac84777757eb2.tar.bz2
android_dalvik-6b1f9f877b70fcc5375fa33a445ac84777757eb2.zip
SamplingProfilerIntegration and SamplingProfiler improvements (1/3)
Summary: frameworks/base - fix profiling to collect data beyond the first snapshot - avoid many small files, accumulate data over process lifetime libcore: - add support for VM specific sampling, trying to cut down overhead - added support for converting snapshot files to text format - fixed race in profiler when stopping dalvik - added VMStack.setThreadStackTrace interface for filling a stack trace into an existing StackTraceElement[] Details: frameworks/base Changed snapshots from text to binary hprof format (bumping version to 3) Changed from one file per snapshot to one file per process lifetime. Restart profiling after snapshot. core/java/com/android/internal/os/SamplingProfilerIntegration.java Add quick test in maybeSnapshot to avoid doing work when the SamplingProfilerIntegration is disabled. Make maybeSnapshot private. Remove unneeded memory allocation in handleLowMemory. core/java/android/app/ActivityThread.java libcore Added ThreadSampler interface. This allows VM specific thread sampling optimizations. The portable version continues to use Thread.getStackTrace(). dalvik/src/main/java/dalvik/system/profiler/ThreadSampler.java dalvik/src/main/java/dalvik/system/profiler/PortableThreadSampler.java dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java Add VMStack.setThreadStackTrace and use in new DalvikThreadSampler to avoid allocating a full stack trace when only a limited depth is desired. dalvik/src/main/java/dalvik/system/profiler/DalvikThreadSampler.java dalvik/src/main/java/dalvik/system/VMStack.java Refactored BinaryHprof.readMagic out of BinaryHprofReader so it can be used by HprofBinaryToAscii converter to probing file types. Added magic number constant to be shared between readMagic and BinaryHprofWriter. dalvik/src/main/java/dalvik/system/profiler/BinaryHprof.java dalvik/src/main/java/dalvik/system/profiler/BinaryHprofReader.java dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java Removed unneeded HprofWriter interface. Changed to simpler static interface to write HprofData to binary and text formats. dalvik/src/main/java/dalvik/system/profiler/HprofWriter.java dalvik/src/main/java/dalvik/system/profiler/AsciiHprofWriter.java dalvik/src/main/java/dalvik/system/profiler/BinaryHprofWriter.java dalvik/src/test/java/dalvik/system/profiler/SamplingProfilerTest.java Added support for reading snapshot files created by SamplingProfilerIntegration by stripping the text header to allow easier conversion to the text format. dalvik/src/main/java/dalvik/system/profiler/HprofBinaryToAscii.java Fixed race between Sampler and SamplingProfiler.stop. SamplingProfiler.stop previously simply called the Sampler's TimerTask.cancel method, but this does not wait for a currently running Sampler to finish. The TimerTask documentation says the only reliable way to do this is to have the run() cancel itself, so that is what is now done, with new code to ensure that SamplingProfiler.stop does not return until the Sampler has been terminated. dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java dalvik Refactored VMStack_getThreadStackTrace to create helper getTraceBuf used to implement new VMStack_setThreadStackTrace. The new version interface fills an existing StackTraceElement[], avoid allocating unnecessary StackTraceElements. vm/native/dalvik_system_VMStack.c Refactor dvmGetStackTraceRaw to create dvmSetStackTraceRaw which fills in an existing, potentially smaller, StackTraceElement[]. vm/Exception.c vm/Exception.h Change stack depths to be size_t to avoid signed/unsigned comparison warnings. vm/Ddm.c vm/Exception.c vm/Exception.h Change-Id: Ie88a3f9e069f6984d790ee61c6f7ac5ed47d3388
-rw-r--r--vm/Ddm.c2
-rw-r--r--vm/Exception.c47
-rw-r--r--vm/Exception.h7
-rw-r--r--vm/native/dalvik_system_VMStack.c70
4 files changed, 91 insertions, 35 deletions
diff --git a/vm/Ddm.c b/vm/Ddm.c
index ee3e9b249..21a38aff3 100644
--- a/vm/Ddm.c
+++ b/vm/Ddm.c
@@ -481,7 +481,7 @@ ArrayObject* dvmDdmGetStackTraceById(u4 threadId)
* and release the thread list lock. If we're being asked to examine
* our own stack trace, skip the suspend/resume.
*/
- int stackDepth = -1;
+ size_t stackDepth;
if (thread != self)
dvmSuspendThread(thread);
traceBuf = dvmFillInStackTraceRaw(thread, &stackDepth);
diff --git a/vm/Exception.c b/vm/Exception.c
index b4b7160bf..c72dcdd63 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -972,13 +972,13 @@ int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
* NOTE: if we support class unloading, we will need to scan the class
* object references out of these arrays.
*/
-void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount)
+void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, size_t* pCount)
{
ArrayObject* stackData = NULL;
int* simpleData = NULL;
void* fp;
void* startFp;
- int stackDepth;
+ size_t stackDepth;
int* intPtr;
if (pCount != NULL)
@@ -1101,11 +1101,8 @@ bail:
ArrayObject* dvmGetStackTrace(const Object* ostackData)
{
const ArrayObject* stackData = (const ArrayObject*) ostackData;
- const int* intVals;
- int stackSize;
-
- stackSize = stackData->length / 2;
- intVals = (const int*) stackData->contents;
+ size_t stackSize = stackData->length / 2;
+ const int* intVals = (const int*) stackData->contents;
return dvmGetStackTraceRaw(intVals, stackSize);
}
@@ -1117,14 +1114,9 @@ ArrayObject* dvmGetStackTrace(const Object* ostackData)
*
* The returned array is not added to the "local refs" list.
*/
-ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
+ArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth)
{
ArrayObject* steArray = NULL;
- int i;
-
- /* init this if we haven't yet */
- if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement))
- dvmInitClass(gDvm.classJavaLangStackTraceElement);
/* allocate a StackTraceElement array */
steArray = dvmAllocArray(gDvm.classJavaLangStackTraceElementArray,
@@ -1132,6 +1124,27 @@ ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
if (steArray == NULL)
goto bail;
+ dvmFillStackTraceElements(intVals, stackDepth, steArray);
+
+bail:
+ dvmReleaseTrackedAlloc((Object*) steArray, NULL);
+ return steArray;
+}
+
+/*
+ * Fills the StackTraceElement array elements from the raw integer
+ * data encoded by dvmFillInStackTrace().
+ *
+ * "intVals" points to the first {method,pc} pair.
+ */
+void dvmFillStackTraceElements(const int* intVals, size_t stackDepth, ArrayObject* steArray)
+{
+ unsigned int i;
+
+ /* init this if we haven't yet */
+ if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement))
+ dvmInitClass(gDvm.classJavaLangStackTraceElement);
+
/*
* Allocate and initialize a StackTraceElement for each stack frame.
* We use the standard constructor to configure the object.
@@ -1148,7 +1161,7 @@ ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
ste = dvmAllocObject(gDvm.classJavaLangStackTraceElement,ALLOC_DEFAULT);
if (ste == NULL)
- goto bail;
+ return;
meth = (Method*) *intVals++;
pc = *intVals++;
@@ -1185,14 +1198,10 @@ ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
dvmReleaseTrackedAlloc((Object*) fileName, NULL);
if (dvmCheckException(dvmThreadSelf()))
- goto bail;
+ return;
dvmSetObjectArrayElement(steArray, i, ste);
}
-
-bail:
- dvmReleaseTrackedAlloc((Object*) steArray, NULL);
- return steArray;
}
/*
diff --git a/vm/Exception.h b/vm/Exception.h
index 6d05b09e1..4ad1af534 100644
--- a/vm/Exception.h
+++ b/vm/Exception.h
@@ -200,17 +200,18 @@ int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
*
* Don't call the "Internal" form of the function directly.
*/
-void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount);
+void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, size_t* pCount);
/* return an [I for use by interpreted code */
INLINE Object* dvmFillInStackTrace(Thread* thread) {
return (Object*) dvmFillInStackTraceInternal(thread, true, NULL);
}
ArrayObject* dvmGetStackTrace(const Object* stackState);
/* return an int* and array count; caller must free() the return value */
-INLINE int* dvmFillInStackTraceRaw(Thread* thread, int* pCount) {
+INLINE int* dvmFillInStackTraceRaw(Thread* thread, size_t* pCount) {
return (int*) dvmFillInStackTraceInternal(thread, false, pCount);
}
-ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth);
+ArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth);
+void dvmFillStackTraceElements(const int* intVals, size_t stackDepth, ArrayObject* steArray);
/*
* Print a formatted version of a raw stack trace to the log file.
diff --git a/vm/native/dalvik_system_VMStack.c b/vm/native/dalvik_system_VMStack.c
index 8db4a6b7d..8d2621bba 100644
--- a/vm/native/dalvik_system_VMStack.c
+++ b/vm/native/dalvik_system_VMStack.c
@@ -168,15 +168,13 @@ bail:
}
/*
- * public static StackTraceElement[] getThreadStackTrace(Thread t)
- *
- * Retrieve the stack trace of the specified thread and return it as an
- * array of StackTraceElement. Returns NULL on failure.
+ * Return a trace buffer for the specified thread or NULL if the
+ * thread is not still alive. *depth is set to the length of a
+ * non-NULL trace buffer. Caller is responsible for freeing the trace
+ * buffer.
*/
-static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
- JValue* pResult)
+static int* getTraceBuf(Object* targetThreadObj, size_t* pStackDepth)
{
- Object* targetThreadObj = (Object*) args[0];
Thread* self = dvmThreadSelf();
Thread* thread;
int* traceBuf;
@@ -193,10 +191,10 @@ static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
break;
}
if (thread == NULL) {
- LOGI("VMStack.getThreadStackTrace: threadObj %p not active\n",
+ LOGI("VMStack.getTraceBuf: threadObj %p not active\n",
targetThreadObj);
dvmUnlockThreadList();
- RETURN_PTR(NULL);
+ return NULL;
}
/*
@@ -204,14 +202,32 @@ static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
* and release the thread list lock. If we're being asked to examine
* our own stack trace, skip the suspend/resume.
*/
- int stackDepth = -1;
if (thread != self)
dvmSuspendThread(thread);
- traceBuf = dvmFillInStackTraceRaw(thread, &stackDepth);
+ traceBuf = dvmFillInStackTraceRaw(thread, pStackDepth);
if (thread != self)
dvmResumeThread(thread);
dvmUnlockThreadList();
+ return traceBuf;
+}
+
+/*
+ * public static StackTraceElement[] getThreadStackTrace(Thread t)
+ *
+ * Retrieve the stack trace of the specified thread and return it as an
+ * array of StackTraceElement. Returns NULL on failure.
+ */
+static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
+ JValue* pResult)
+{
+ Object* targetThreadObj = (Object*) args[0];
+ size_t stackDepth;
+ int* traceBuf = getTraceBuf(targetThreadObj, &stackDepth);
+
+ if (traceBuf == NULL)
+ RETURN_PTR(NULL);
+
/*
* Convert the raw buffer into an array of StackTraceElement.
*/
@@ -220,16 +236,46 @@ static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
RETURN_PTR(trace);
}
+/*
+ * public static int fillStackTraceElements(Thread t, StackTraceElement[] stackTraceElements)
+ *
+ * Retrieve a partial stack trace of the specified thread and return
+ * the number of frames filled. Returns 0 on failure.
+ */
+static void Dalvik_dalvik_system_VMStack_fillStackTraceElements(const u4* args,
+ JValue* pResult)
+{
+ Object* targetThreadObj = (Object*) args[0];
+ ArrayObject* steArray = (ArrayObject*) args[1];
+ size_t stackDepth;
+ int* traceBuf = getTraceBuf(targetThreadObj, &stackDepth);
+
+ if (traceBuf == NULL)
+ RETURN_PTR(NULL);
+
+ /*
+ * Set the raw buffer into an array of StackTraceElement.
+ */
+ if (stackDepth > steArray->length) {
+ stackDepth = steArray->length;
+ }
+ dvmFillStackTraceElements(traceBuf, stackDepth, steArray);
+ free(traceBuf);
+ RETURN_INT(stackDepth);
+}
+
const DalvikNativeMethod dvm_dalvik_system_VMStack[] = {
{ "getCallingClassLoader", "()Ljava/lang/ClassLoader;",
Dalvik_dalvik_system_VMStack_getCallingClassLoader },
{ "getCallingClassLoader2", "()Ljava/lang/ClassLoader;",
Dalvik_dalvik_system_VMStack_getCallingClassLoader2 },
- { "getStackClass2", "()Ljava/lang/Class;",
+ { "getStackClass2", "()Ljava/lang/Class;",
Dalvik_dalvik_system_VMStack_getStackClass2 },
{ "getClasses", "(IZ)[Ljava/lang/Class;",
Dalvik_dalvik_system_VMStack_getClasses },
{ "getThreadStackTrace", "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;",
Dalvik_dalvik_system_VMStack_getThreadStackTrace },
+ { "fillStackTraceElements", "(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I",
+ Dalvik_dalvik_system_VMStack_fillStackTraceElements },
{ NULL, NULL, NULL },
};