Add art support for sample profiling from traceview gui.
Change-Id: I6004bf143521b872084ca4aae873bea3524aa895
(cherry picked from commit 23009dca63c1699e28bfeaa8b45ca48fa0e86ace)
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index e3ec3bc..8a8b461 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -37,6 +37,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");
return toStringArray(env, features);
@@ -58,8 +59,9 @@
Runtime::Current()->ResetStats(kinds);
}
-static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags) {
- Trace::Start("[DDMS]", -1, bufferSize, flags, true);
+static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
+ jboolean samplingEnabled, jint intervalUs) {
+ Trace::Start("[DDMS]", -1, bufferSize, flags, true, samplingEnabled, intervalUs);
}
static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -82,7 +84,7 @@
if (traceFilename.c_str() == NULL) {
return;
}
- Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false);
+ Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false, false, 0);
}
static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -91,7 +93,7 @@
if (traceFilename.c_str() == NULL) {
return;
}
- Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false);
+ Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false, false, 0);
}
static jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
@@ -322,7 +324,7 @@
NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
- NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(II)V"),
+ NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V"),
NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;II)V"),
NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 51a67c1..5679d4e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -925,7 +925,8 @@
method_trace_file_size_ = options->method_trace_file_size_;
if (options->method_trace_) {
- Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0, false);
+ Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0,
+ false, false, 0);
}
VLOG(startup) << "Runtime::Init exiting";
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 4c092fd..6d040e1 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -122,9 +122,6 @@
#endif
Trace* volatile Trace::the_trace_ = NULL;
-// TODO: Add way to enable sampling and set interval through gui.
-bool Trace::sampling_enabled_ = true;
-uint32_t Trace::sampling_interval_us_ = 1000;
pthread_t Trace::sampling_pthread_ = 0U;
UniquePtr<std::vector<mirror::ArtMethod*> > Trace::temp_stack_trace_;
@@ -301,11 +298,12 @@
void* Trace::RunSamplingThread(void* arg) {
Runtime* runtime = Runtime::Current();
+ int interval_us = reinterpret_cast<int>(arg);
CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
!runtime->IsCompiler()));
while (true) {
- usleep(sampling_interval_us_);
+ usleep(interval_us);
ATRACE_BEGIN("Profile sampling");
Thread* self = Thread::Current();
Trace* the_trace;
@@ -331,7 +329,7 @@
}
void Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
- bool direct_to_ddms) {
+ bool direct_to_ddms, bool sampling_enabled, int interval_us) {
Thread* self = Thread::Current();
{
MutexLock mu(self, *Locks::trace_lock_);
@@ -367,16 +365,19 @@
if (the_trace_ != NULL) {
LOG(ERROR) << "Trace already in progress, ignoring this request";
} else {
- the_trace_ = new Trace(trace_file.release(), buffer_size, flags);
+ the_trace_ = new Trace(trace_file.release(), buffer_size, flags, sampling_enabled);
// Enable count of allocs if specified in the flags.
if ((flags && kTraceCountAllocs) != 0) {
runtime->SetStatsEnabled(true);
}
- if (sampling_enabled_) {
- CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread, NULL),
- "Sampling profiler thread");
+
+
+ if (sampling_enabled) {
+ CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread,
+ reinterpret_cast<void*>(interval_us)),
+ "Sampling profiler thread");
} else {
runtime->GetInstrumentation()->AddListener(the_trace_,
instrumentation::Instrumentation::kMethodEntered |
@@ -407,7 +408,7 @@
if (the_trace != NULL) {
the_trace->FinishTracing();
- if (sampling_enabled_) {
+ if (the_trace->sampling_enabled_) {
MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, NULL);
} else {
@@ -420,7 +421,7 @@
}
runtime->GetThreadList()->ResumeAll();
- if (sampling_enabled_ && sampling_pthread != 0U) {
+ if (sampling_pthread != 0U) {
CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown");
}
}
@@ -436,10 +437,10 @@
return the_trace_ != NULL;
}
-Trace::Trace(File* trace_file, int buffer_size, int flags)
+Trace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled)
: trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
- clock_source_(default_clock_source_), buffer_size_(buffer_size), start_time_(MicroTime()),
- cur_offset_(0), overflow_(false) {
+ sampling_enabled_(sampling_enabled), clock_source_(default_clock_source_),
+ buffer_size_(buffer_size), start_time_(MicroTime()), cur_offset_(0), overflow_(false) {
// Set up the beginning of the trace.
uint16_t trace_version = GetTraceVersion(clock_source_);
memset(buf_.get(), 0, kTraceHeaderLength);
@@ -456,10 +457,6 @@
cur_offset_ = kTraceHeaderLength;
}
-Trace::~Trace() {
- CHECK_EQ(sampling_pthread_, static_cast<pthread_t>(0U));
-}
-
static void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint8_t* ptr = buf + kTraceHeaderLength;
diff --git a/runtime/trace.h b/runtime/trace.h
index 6fc3790..06cb6a6 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -51,7 +51,7 @@
static void SetDefaultClockSource(ProfilerClockSource clock_source);
static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
- bool direct_to_ddms)
+ bool direct_to_ddms, bool sampling_enabled, int interval_us)
LOCKS_EXCLUDED(Locks::mutator_lock_,
Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_,
@@ -88,11 +88,10 @@
// Clear and store an old stack trace for later use.
static void FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace);
- ~Trace();
-
private:
- explicit Trace(File* trace_file, int buffer_size, int flags);
+ explicit Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled);
+ // The sampling interval in microseconds is passed as an argument.
static void* RunSamplingThread(void* arg) LOCKS_EXCLUDED(Locks::trace_lock_);
void FinishTracing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -115,12 +114,6 @@
// The default profiler clock source.
static ProfilerClockSource default_clock_source_;
- // True if traceview should sample instead of instrumenting method entry/exit.
- static bool sampling_enabled_;
-
- // Sampling interval in microseconds.
- static uint32_t sampling_interval_us_;
-
// Sampling thread, non-zero when sampling.
static pthread_t sampling_pthread_;
@@ -136,6 +129,9 @@
// Flags enabling extra tracing of things such as alloc counts.
const int flags_;
+ // True if traceview should sample instead of instrumenting method entry/exit.
+ const bool sampling_enabled_;
+
const ProfilerClockSource clock_source_;
// Size of buf_.