Add dalvik support for sample profiling from traceview gui.
(cherry picked from commit 86bb14a3e4d7ef3b8b4240bbc2a8b989a1b8c7c0)
Change-Id: Ifece45f6a6644c20b6681a58dd3eae3534ad47e4
diff --git a/vm/Profile.cpp b/vm/Profile.cpp
index 8492cd5..08e1463 100644
--- a/vm/Profile.cpp
+++ b/vm/Profile.cpp
@@ -276,10 +276,12 @@
}
/*
- * Entry point for sampling thread.
+ * Entry point for sampling thread. The sampling interval in microseconds is
+ * passed in as an argument.
*/
static void* runSamplingThread(void* arg)
{
+ int intervalUs = (int) arg;
while (gDvm.methodTrace.traceEnabled) {
dvmSuspendAllThreads(SUSPEND_FOR_SAMPLING);
@@ -291,7 +293,7 @@
dvmResumeAllThreads(SUSPEND_FOR_SAMPLING);
- usleep(gDvm.methodTrace.samplingIntervalUs);
+ usleep(intervalUs);
}
return NULL;
}
@@ -500,7 +502,7 @@
* On failure, we throw an exception and return.
*/
void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize,
- int flags, bool directToDdms)
+ int flags, bool directToDdms, bool samplingEnabled, int intervalUs)
{
MethodTraceState* state = &gDvm.methodTrace;
@@ -569,9 +571,7 @@
state->recordSize = TRACE_REC_SIZE_SINGLE_CLOCK;
}
- /* TODO: Control sampling through gui. */
- state->samplingEnabled = false;
- state->samplingIntervalUs = 1000;
+ state->samplingEnabled = samplingEnabled;
/*
* Output the header.
@@ -597,11 +597,11 @@
* following to take a Thread* argument, and set the appropriate
* interpBreak flags only on the target thread.
*/
- if (state->samplingEnabled) {
+ if (samplingEnabled) {
updateActiveProfilers(kSubModeSampleTrace, true);
/* Start the sampling thread. */
if (!dvmCreateInternalThread(&state->samplingThreadHandle,
- "Sampling Thread", &runSamplingThread, NULL)) {
+ "Sampling Thread", &runSamplingThread, (void*) intervalUs)) {
dvmThrowInternalError("failed to create sampling thread");
goto fail;
}
@@ -706,6 +706,7 @@
void dvmMethodTraceStop()
{
MethodTraceState* state = &gDvm.methodTrace;
+ bool samplingEnabled = state->samplingEnabled;
u8 elapsed;
/*
@@ -720,7 +721,7 @@
dvmUnlockMutex(&state->startStopLock);
return;
} else {
- if (state->samplingEnabled) {
+ if (samplingEnabled) {
updateActiveProfilers(kSubModeSampleTrace, false);
} else {
updateActiveProfilers(kSubModeMethodTrace, false);
@@ -879,7 +880,7 @@
state->traceFile = NULL;
/* free and clear sampling traces held by all threads */
- if (state->samplingEnabled) {
+ if (samplingEnabled) {
freeThreadStackTraceSamples();
}
@@ -888,7 +889,7 @@
dvmUnlockMutex(&state->startStopLock);
/* make sure the sampling thread has stopped */
- if (state->samplingEnabled &&
+ if (samplingEnabled &&
pthread_join(state->samplingThreadHandle, NULL) != 0) {
ALOGW("Sampling thread join failed");
}
diff --git a/vm/Profile.h b/vm/Profile.h
index 0ec8705..6a2c4be 100644
--- a/vm/Profile.h
+++ b/vm/Profile.h
@@ -54,7 +54,6 @@
size_t recordSize;
bool samplingEnabled;
- int samplingIntervalUs;
pthread_t samplingThreadHandle;
};
@@ -87,7 +86,7 @@
* Start/stop method tracing.
*/
void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize,
- int flags, bool directToDdms);
+ int flags, bool directToDdms, bool samplingEnabled, int intervalUs);
bool dvmIsMethodTraceActive(void);
void dvmMethodTraceStop(void);
diff --git a/vm/native/dalvik_system_VMDebug.cpp b/vm/native/dalvik_system_VMDebug.cpp
index d03f6f4..8ba304a 100644
--- a/vm/native/dalvik_system_VMDebug.cpp
+++ b/vm/native/dalvik_system_VMDebug.cpp
@@ -56,6 +56,7 @@
std::vector<std::string> features;
features.push_back("method-trace-profiling");
features.push_back("method-trace-profiling-streaming");
+ features.push_back("method-sample-profiling");
features.push_back("hprof-heap-dump");
features.push_back("hprof-heap-dump-streaming");
@@ -224,16 +225,30 @@
}
/*
- * static void startMethodTracingNative(String traceFileName,
- * FileDescriptor fd, int bufferSize, int flags)
+ * static void startMethodTracingDdmsImpl(int bufferSize, int flags,
+ * boolean samplingEnabled, int intervalUs)
*
- * Start method trace profiling.
- *
- * If both "traceFileName" and "fd" are null, the result will be sent
- * directly to DDMS. (The non-DDMS versions of the calls are expected
- * to enforce non-NULL filenames.)
+ * Start method trace profiling, sending results directly to DDMS.
*/
-static void Dalvik_dalvik_system_VMDebug_startMethodTracingNative(const u4* args,
+static void Dalvik_dalvik_system_VMDebug_startMethodTracingDdmsImpl(const u4* args,
+ JValue* pResult)
+{
+ int bufferSize = args[0];
+ int flags = args[1];
+ bool samplingEnabled = args[2];
+ int intervalUs = args[3];
+ dvmMethodTraceStart("[DDMS]", -1, bufferSize, flags, true, samplingEnabled,
+ intervalUs);
+ RETURN_VOID();
+}
+
+/*
+ * static void startMethodTracingFd(String traceFileName, FileDescriptor fd,
+ * int bufferSize, int flags)
+ *
+ * Start method trace profiling, sending results to a file descriptor.
+ */
+static void Dalvik_dalvik_system_VMDebug_startMethodTracingFd(const u4* args,
JValue* pResult)
{
StringObject* traceFileStr = (StringObject*) args[0];
@@ -241,36 +256,46 @@
int bufferSize = args[2];
int flags = args[3];
- if (bufferSize == 0) {
- // Default to 8MB per the documentation.
- bufferSize = 8 * 1024 * 1024;
- }
+ int origFd = getFileDescriptor(traceFd);
+ if (origFd < 0)
+ RETURN_VOID();
- if (bufferSize < 1024) {
- dvmThrowIllegalArgumentException(NULL);
+ int fd = dup(origFd);
+ if (fd < 0) {
+ dvmThrowExceptionFmt(gDvm.exRuntimeException,
+ "dup(%d) failed: %s", origFd, strerror(errno));
RETURN_VOID();
}
- char* traceFileName = NULL;
- if (traceFileStr != NULL)
- traceFileName = dvmCreateCstrFromString(traceFileStr);
-
- int fd = -1;
- if (traceFd != NULL) {
- int origFd = getFileDescriptor(traceFd);
- if (origFd < 0)
- RETURN_VOID();
-
- fd = dup(origFd);
- if (fd < 0) {
- dvmThrowExceptionFmt(gDvm.exRuntimeException,
- "dup(%d) failed: %s", origFd, strerror(errno));
- RETURN_VOID();
- }
+ char* traceFileName = dvmCreateCstrFromString(traceFileStr);
+ if (traceFileName == NULL) {
+ RETURN_VOID();
}
- dvmMethodTraceStart(traceFileName != NULL ? traceFileName : "[DDMS]",
- fd, bufferSize, flags, (traceFileName == NULL && fd == -1));
+ dvmMethodTraceStart(traceFileName, fd, bufferSize, flags, false, false, 0);
+ free(traceFileName);
+ RETURN_VOID();
+}
+
+/*
+ * static void startMethodTracingFilename(String traceFileName, int bufferSize,
+ * int flags)
+ *
+ * Start method trace profiling, sending results to a file.
+ */
+static void Dalvik_dalvik_system_VMDebug_startMethodTracingFilename(const u4* args,
+ JValue* pResult)
+{
+ StringObject* traceFileStr = (StringObject*) args[0];
+ int bufferSize = args[1];
+ int flags = args[2];
+
+ char* traceFileName = dvmCreateCstrFromString(traceFileStr);
+ if (traceFileName == NULL) {
+ RETURN_VOID();
+ }
+
+ dvmMethodTraceStart(traceFileName, -1, bufferSize, flags, false, false, 0);
free(traceFileName);
RETURN_VOID();
}
@@ -796,8 +821,12 @@
Dalvik_dalvik_system_VMDebug_startAllocCounting },
{ "stopAllocCounting", "()V",
Dalvik_dalvik_system_VMDebug_stopAllocCounting },
- { "startMethodTracingNative", "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V",
- Dalvik_dalvik_system_VMDebug_startMethodTracingNative },
+ { "startMethodTracingDdmsImpl", "(IIZI)V",
+ Dalvik_dalvik_system_VMDebug_startMethodTracingDdmsImpl },
+ { "startMethodTracingFd", "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V",
+ Dalvik_dalvik_system_VMDebug_startMethodTracingFd },
+ { "startMethodTracingFilename", "(Ljava/lang/String;II)V",
+ Dalvik_dalvik_system_VMDebug_startMethodTracingFilename },
{ "isMethodTracingActive", "()Z",
Dalvik_dalvik_system_VMDebug_isMethodTracingActive },
{ "stopMethodTracing", "()V",