Fix the TODOs in the traceview support.
Change-Id: Iefd57761231820afec7278345dcefd1c7eae4a77
diff --git a/src/runtime.cc b/src/runtime.cc
index c452771..e033059 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -465,6 +465,12 @@
parsed->method_trace_file_ = option.substr(strlen("-Xmethod-trace-file:"));
} else if (StartsWith(option, "-Xmethod-trace-file-size:")) {
parsed->method_trace_file_size_ = ParseIntegerOrDie(option);
+ } else if (option == "-Xprofile:threadcpuclock") {
+ Trace::SetDefaultClockSource(kProfilerClockSourceThreadCpu);
+ } else if (option == "-Xprofile:wallclock") {
+ Trace::SetDefaultClockSource(kProfilerClockSourceWall);
+ } else if (option == "-Xprofile:dualclock") {
+ Trace::SetDefaultClockSource(kProfilerClockSourceDual);
} else {
if (!ignore_unrecognized) {
// TODO: print usage via vfprintf
diff --git a/src/trace.cc b/src/trace.cc
index 7b7a767..aa6c523 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -32,6 +32,40 @@
namespace art {
+// File format:
+// header
+// record 0
+// record 1
+// ...
+//
+// Header format:
+// u4 magic ('SLOW')
+// u2 version
+// u2 offset to data
+// u8 start date/time in usec
+// u2 record size in bytes (version >= 2 only)
+// ... padding to 32 bytes
+//
+// Record format v1:
+// u1 thread ID
+// u4 method ID | method action
+// u4 time delta since start, in usec
+//
+// Record format v2:
+// u2 thread ID
+// u4 method ID | method action
+// u4 time delta since start, in usec
+//
+// Record format v3:
+// u2 thread ID
+// u4 method ID | method action
+// u4 time delta since start, in usec
+// u4 wall time since start, in usec (when clock == "dual" only)
+//
+// 32 bits of microseconds is 70 minutes.
+//
+// All values are stored in little-endian order.
+
static const uint32_t kTraceMethodActionMask = 0x03; // two bits
static const char kTraceTokenChar = '*';
static const uint16_t kTraceHeaderLength = 32;
@@ -41,44 +75,57 @@
static const uint16_t kTraceRecordSizeSingleClock = 10; // using v2
static const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps
+static ProfilerClockSource gDefaultTraceClockSource = kProfilerClockSourceDual;
+
static inline uint32_t TraceMethodId(uint32_t methodValue) {
return (methodValue & ~kTraceMethodActionMask);
}
+
static inline uint32_t TraceMethodCombine(uint32_t method, uint8_t traceEvent) {
return (method | traceEvent);
}
-static bool UseThreadCpuClock() {
- // TODO: Allow control over which clock is used
- return true;
+void Trace::SetDefaultClockSource(ProfilerClockSource clock_source) {
+ gDefaultTraceClockSource = clock_source;
}
-static bool UseWallClock() {
- // TODO: Allow control over which clock is used
- return true;
+bool Trace::UseThreadCpuClock() {
+#if defined(HAVE_POSIX_CLOCKS)
+ return clock_source_ != kProfilerClockSourceWall;
+#else
+ return false;
+#endif
}
-static void MeasureClockOverhead() {
- if (UseThreadCpuClock()) {
+bool Trace::UseWallClock() {
+#if defined(HAVE_POSIX_CLOCKS)
+ return clock_source_ != kProfilerClockSourceThreadCpu;
+#else
+ return true;
+#endif
+}
+
+static void MeasureClockOverhead(Trace* trace) {
+ if (trace->UseThreadCpuClock()) {
ThreadCpuMicroTime();
}
- if (UseWallClock()) {
+ if (trace->UseWallClock()) {
MicroTime();
}
}
-static uint32_t GetClockOverhead() {
+static uint32_t GetClockOverhead(Trace* trace) {
uint64_t start = ThreadCpuMicroTime();
for (int i = 4000; i > 0; i--) {
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
- MeasureClockOverhead();
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
+ MeasureClockOverhead(trace);
}
uint64_t elapsed = ThreadCpuMicroTime() - start;
@@ -204,6 +251,12 @@
RemoveSavedCodeFromMap(method);
}
+Trace::Trace(File* trace_file, int buffer_size, int flags)
+ : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
+ clock_source_(gDefaultTraceClockSource), overflow_(false),
+ buffer_size_(buffer_size), start_time_(0), trace_version_(0), record_size_(0), cur_offset_(0) {
+}
+
void Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags, bool direct_to_ddms) {
if (Runtime::Current()->IsMethodTracingActive()) {
LOG(INFO) << "Trace already in progress, ignoring this request";
@@ -306,7 +359,7 @@
uint64_t elapsed = MicroTime() - start_time_;
size_t final_offset = cur_offset_;
- uint32_t clock_overhead = GetClockOverhead();
+ uint32_t clock_overhead = GetClockOverhead(this);
if ((flags_ & kTraceCountAllocs) != 0) {
Runtime::Current()->SetStatsEnabled(false);
diff --git a/src/trace.h b/src/trace.h
index bcf7f0a..0042fc2 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -43,9 +43,14 @@
uintptr_t return_pc_;
};
+enum ProfilerClockSource {
+ kProfilerClockSourceThreadCpu,
+ kProfilerClockSourceWall,
+ kProfilerClockSourceDual,
+};
+
class Trace {
public:
-
enum TraceEvent {
kMethodTraceEnter = 0,
kMethodTraceExit = 1,
@@ -56,10 +61,15 @@
kTraceCountAllocs = 1,
};
+ 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);
static void Stop();
static void Shutdown();
+ bool UseWallClock();
+ bool UseThreadCpuClock();
+
void LogMethodTraceEvent(Thread* self, const Method* method, TraceEvent event);
void AddSavedCodeToMap(const Method* method, const void* code);
@@ -70,10 +80,7 @@
void ResetSavedCode(Method* method);
private:
- explicit Trace(File* trace_file, int buffer_size, int flags)
- : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags), overflow_(false),
- buffer_size_(buffer_size), start_time_(0), trace_version_(0), record_size_(0), cur_offset_(0) {
- }
+ explicit Trace(File* trace_file, int buffer_size, int flags);
void BeginTracing();
void FinishTracing();
@@ -107,6 +114,8 @@
// Flags enabling extra tracing of things such as alloc counts.
int flags_;
+ ProfilerClockSource clock_source_;
+
bool overflow_;
int buffer_size_;
uint64_t start_time_;