OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/debug/trace_event_impl.h" | |
6 | |
7 #include <fcntl.h> | |
8 | |
9 #include "base/debug/trace_event.h" | |
10 #include "base/file_util.h" | |
11 #include "base/format_macros.h" | |
12 #include "base/logging.h" | |
13 #include "base/stringprintf.h" | |
14 | |
15 namespace { | |
16 | |
17 int g_atrace_fd = -1; | |
18 const char* kATraceMarkerFile = "/sys/kernel/debug/tracing/trace_marker"; | |
19 | |
20 } // namespace | |
21 | |
22 namespace base { | |
23 namespace debug { | |
24 | |
25 // static | |
26 void TraceLog::InitATrace() { | |
27 DCHECK(g_atrace_fd == -1); | |
28 g_atrace_fd = open(kATraceMarkerFile, O_WRONLY | O_APPEND); | |
29 if (g_atrace_fd == -1) | |
30 LOG(WARNING) << "Couldn't open " << kATraceMarkerFile; | |
31 } | |
32 | |
33 // static | |
34 bool TraceLog::IsATraceEnabled() { | |
35 return g_atrace_fd != -1; | |
36 } | |
37 | |
38 void TraceLog::SendToATrace(char phase, | |
39 const char* category, | |
40 const char* name, | |
41 int num_args, | |
42 const char** arg_names, | |
43 const unsigned char* arg_types, | |
44 const unsigned long long* arg_values) { | |
45 if (!IsATraceEnabled()) | |
46 return; | |
47 | |
48 switch (phase) { | |
49 case TRACE_EVENT_PHASE_BEGIN: | |
50 case TRACE_EVENT_PHASE_INSTANT: { | |
51 std::string out = StringPrintf("B|%d|%s-%s", getpid(), category, name); | |
jbates
2012/10/30 20:22:14
There's plenty of room for performance improvement
Xianzhu
2012/10/30 21:45:01
Could you be more specific? Do you mean the "+=",
jbates
2012/10/31 22:26:01
Yep, StringPrintf and std::string temporaries are
| |
52 for (int i = 0; i < num_args; ++i) { | |
53 out += '|'; | |
54 out += arg_names[i]; | |
55 out += '='; | |
56 TraceEvent::TraceValue value; | |
57 value.as_uint = arg_values[i]; | |
58 std::string::size_type value_start = out.length(); | |
59 TraceEvent::AppendValueAsJSON(arg_types[i], value, &out); | |
60 // Remove the quotes which may confuse the atrace script. | |
61 ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); | |
62 ReplaceSubstringsAfterOffset(&out, value_start, "\"", ""); | |
63 } | |
64 write(g_atrace_fd, out.c_str(), out.size()); | |
65 | |
66 if (phase != TRACE_EVENT_PHASE_INSTANT) | |
67 break; | |
68 // Fall through. Simulate an instance event with a pair of begin/end. | |
69 } | |
70 case TRACE_EVENT_PHASE_END: { | |
71 // Though a single 'E' is enough, here append pid and name so that | |
72 // unpaired events can be found easily. | |
73 std::string out = StringPrintf("E|%d|%s-%s", getpid(), category, name); | |
74 write(g_atrace_fd, out.c_str(), out.size()); | |
75 break; | |
76 } | |
77 case TRACE_EVENT_PHASE_COUNTER: | |
78 for (int i = 0; i < num_args; ++i) { | |
79 DCHECK(arg_types[i] == TRACE_VALUE_TYPE_INT); | |
80 std::string out = StringPrintf( | |
81 "C|%d|%s-%s-%s|%d", | |
82 getpid(), category, name, | |
83 arg_names[i], static_cast<int>(arg_values[i])); | |
84 write(g_atrace_fd, out.c_str(), out.size()); | |
85 } | |
86 break; | |
87 | |
88 default: | |
89 // Do nothing. | |
90 break; | |
91 } | |
92 } | |
93 | |
94 void TraceLog::AddClockSyncMetadataEvents() { | |
95 // Since Android does not support sched_setaffinity, we cannot establish clock | |
96 // sync unless the scheduler clock is set to global. If the trace_clock file | |
97 // can't be read, we will assume the kernel doesn't support tracing and do | |
98 // nothing. | |
99 std::string clock_mode; | |
100 if (!file_util::ReadFileToString( | |
101 FilePath("/sys/kernel/debug/tracing/trace_clock"), &clock_mode)) | |
102 return; | |
103 | |
104 if (clock_mode != "local [global]\n") { | |
105 DLOG(WARNING) << | |
106 "The kernel's tracing clock must be set to global in order for " << | |
107 "trace_event to be synchronized with . Do this by\n" << | |
108 " echo global > /sys/kerel/debug/tracing/trace_clock"; | |
109 return; | |
110 } | |
111 | |
112 int atrace_fd = g_atrace_fd; | |
113 if (atrace_fd == -1) { | |
114 // This function may be called when atrace is not enabled. | |
115 atrace_fd = open(kATraceMarkerFile, O_WRONLY | O_APPEND); | |
116 if (atrace_fd == -1) { | |
117 LOG(WARNING) << "Couldn't open " << kATraceMarkerFile; | |
118 return; | |
119 } | |
120 } | |
121 | |
122 // Android's kernel trace system has a trace_marker feature: this is a file on | |
123 // debugfs that takes the written data and pushes it onto the trace | |
124 // buffer. So, to establish clock sync, we write our monotonic clock into that | |
125 // trace buffer. | |
126 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); | |
127 double now_in_seconds = now.ToInternalValue() / 1000000.0; | |
128 std::string marker = StringPrintf( | |
129 "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds); | |
130 if (write(atrace_fd, marker.c_str(), marker.size()) != 0) { | |
131 DLOG(WARNING) << "Couldn't write to " << kATraceMarkerFile << ": " | |
132 << strerror(errno); | |
133 } | |
134 | |
135 if (g_atrace_fd == -1) | |
136 close(atrace_fd); | |
137 } | |
138 | |
139 } // namespace debug | |
140 } // namespace base | |
OLD | NEW |