diff options
author | Brian Carlstrom <bdc@google.com> | 2011-03-28 00:12:36 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2011-03-29 17:14:55 -0700 |
commit | 6b1f9f877b70fcc5375fa33a445ac84777757eb2 (patch) | |
tree | a1fd672e954402093822130ace532090b0fab543 | |
parent | 4624f350313daaae52068c5d1d12b88859d43e54 (diff) | |
download | android_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.c | 2 | ||||
-rw-r--r-- | vm/Exception.c | 47 | ||||
-rw-r--r-- | vm/Exception.h | 7 | ||||
-rw-r--r-- | vm/native/dalvik_system_VMStack.c | 70 |
4 files changed, 91 insertions, 35 deletions
@@ -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 }, }; |