Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: base/debug/trace_event.cc

Issue 6862002: Merge gpu_trace_event back into base/debug/trace_event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: "fix gpu/command_buffer/client/cmd_buffer_helper to new macros" Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event.h" 5 #include "base/debug/trace_event.h"
6 6
7 #if defined(OS_WIN)
8 #include "base/debug/trace_event_win.h"
9 #endif
7 #include "base/format_macros.h" 10 #include "base/format_macros.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/path_service.h"
11 #include "base/process_util.h" 11 #include "base/process_util.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
15 #include "base/time.h" 14 #include "base/time.h"
16 15
17 #define USE_UNRELIABLE_NOW 16 #define USE_UNRELIABLE_NOW
18 17
19 namespace base { 18 namespace base {
20 namespace debug { 19 namespace debug {
21 20
22 static const char* kEventTypeNames[] = { 21 // Controls the number of trace events we will buffer in-memory
23 "BEGIN", 22 // before throwing them away.
24 "END", 23 #define TRACE_EVENT_BUFFER_SIZE 500000
25 "INSTANT" 24 #define TRACE_EVENT_BATCH_SIZE 1000
26 }; 25
27 26 ////////////////////////////////////////////////////////////////////////////////
28 static const FilePath::CharType* kLogFileName = 27 //
29 FILE_PATH_LITERAL("trace_%d.log"); 28 // TraceLog::Category
29 //
30 ////////////////////////////////////////////////////////////////////////////////
31 TraceCategory::TraceCategory(const char* name, bool enabled)
32 : name_(name) {
33 base::subtle::NoBarrier_Store(&enabled_,
34 static_cast<base::subtle::Atomic32>(enabled));
35 }
36
37 TraceCategory::~TraceCategory() {
38 base::subtle::NoBarrier_Store(&enabled_,
39 static_cast<base::subtle::Atomic32>(0));
40 }
41
42 ////////////////////////////////////////////////////////////////////////////////
43 //
44 // TraceEvent
45 //
46 ////////////////////////////////////////////////////////////////////////////////
47
48 namespace {
49 const char* GetPhaseStr(TraceEventPhase phase) {
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: one blank line after opening namespace.
scheib 2011/04/27 21:20:10 Done.
50 if (phase== TRACE_EVENT_PHASE_BEGIN) {
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: phase ==
Sigurður Ásgeirsson 2011/04/15 17:41:45 perhaps this is better phrased as a switch?
scheib 2011/04/27 21:20:10 Done.
scheib 2011/04/27 21:20:10 Done.
scheib 2011/04/27 21:20:10 Done.
51 return "B";
52 } else if (phase == TRACE_EVENT_PHASE_INSTANT) {
53 return "I";
54 } else if (phase == TRACE_EVENT_PHASE_END) {
55 return "E";
56 } else {
57 DCHECK(false);
58 return "?";
59 }
60 }
61 }
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: one blank line before closing namespace } //
scheib 2011/04/27 21:20:10 Done.
62
63 TraceEvent::TraceEvent()
64 : processId(0),
65 threadId(0),
66 phase(TRACE_EVENT_PHASE_BEGIN),
67 category(NULL),
68 name(NULL) {
69 memset(&argNames, 0, sizeof(argNames));
70 }
71
72 TraceEvent::~TraceEvent() {
73 }
74
75 void TraceEvent::AppendAsJSON(std::string* out,
Sigurður Ásgeirsson 2011/04/15 17:41:45 First input args, then output args: http://google
scheib 2011/04/27 21:20:10 Done.
76 const std::vector<TraceEvent>& events,
77 size_t start,
78 size_t count) {
79 *out += "[";
80 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
81 if (i > 0)
82 *out += ",";
83 events[i + start].AppendAsJSON(out);
84 }
85 *out += "]";
86 }
87
88 void TraceEvent::AppendAsJSON(std::string* out) const {
89 int nargs = 0;
Sigurður Ásgeirsson 2011/04/15 17:41:45 some running commentary would make this function e
scheib 2011/04/27 21:20:10 Done.
90 for (int i = 0; i < TRACE_MAX_NUM_ARGS; ++i) {
91 if (argNames[i] == NULL)
92 break;
93 nargs += 1;
94 }
95
96 const char* phaseStr = GetPhaseStr(phase);
Sigurður Ásgeirsson 2011/04/15 17:41:45 phaseStr->phase_str
scheib 2011/04/27 21:20:10 Done.
97 int64 time_int64 = timestamp.ToInternalValue();
98 long long unsigned int time_llui =
99 static_cast<long long unsigned int>(time_int64);
100 StringAppendF(out,
101 "{cat:'%s',pid:%i,tid:%i,ts:0x%llx,ph:'%s',name:'%s',args:{",
102 category->name(),
103 static_cast<int>(processId),
104 static_cast<int>(threadId),
105 time_llui,
106 phaseStr,
107 name);
108 for (int i = 0; i < nargs; ++i) {
109 if (i > 0)
110 *out += ",";
111 *out += argNames[i];
112 *out += ":'";
113 *out += argValues[i];
114 *out += "'";
115 }
116 *out += "}}";
117 }
118
119 ////////////////////////////////////////////////////////////////////////////////
120 //
121 // TraceLog
122 //
123 ////////////////////////////////////////////////////////////////////////////////
30 124
31 // static 125 // static
32 TraceLog* TraceLog::GetInstance() { 126 TraceLog* TraceLog::GetInstance() {
33 return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); 127 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
34 } 128 }
35 129
36 // static 130 TraceLog::TraceLog()
37 bool TraceLog::IsTracing() { 131 : enabled_(false)
38 return TraceLog::GetInstance()->enabled_; 132 {
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: bracket placement.
scheib 2011/04/27 21:20:10 Done.
39 } 133 logged_events_.reserve(1024);
40 134 }
41 // static 135
42 bool TraceLog::StartTracing() { 136 TraceLog::~TraceLog() {
43 return TraceLog::GetInstance()->Start(); 137 }
44 } 138
45 139 TraceCategory* TraceLog::GetCategory(const char* name) {
46 // static 140 AutoLock lock(lock_);
47 void TraceLog::StopTracing() { 141 // TODO(nduca): replace with a hash_map.
Sigurður Ásgeirsson 2011/04/15 17:41:45 Yes, suggest adding an efficient name lookup befor
scheib 2011/04/27 21:20:10 Categories moved to static array. Categories are c
48 return TraceLog::GetInstance()->Stop(); 142 for (int i = static_cast<int>(categories_.size()) - 1; i >= 0; i-- ) {
49 } 143 if (strcmp(categories_[i]->name(), name) == 0)
50 144 return categories_[i];
51 void TraceLog::Trace(const std::string& name, 145 }
52 EventType type, 146 TraceCategory* category = new TraceCategory(name, enabled_);
53 const void* id, 147 categories_.push_back(category);
54 const std::wstring& extra, 148 return category;
55 const char* file, 149 }
56 int line) { 150
57 if (!enabled_) 151 void TraceLog::SetEnabled(bool enabled) {
152 AutoLock lock(lock_);
153 if (enabled == enabled_)
58 return; 154 return;
59 Trace(name, type, id, WideToUTF8(extra), file, line); 155 if (enabled) {
60 } 156 // Enable all categories
61 157 enabled_ = true;
62 void TraceLog::Trace(const std::string& name, 158 for (size_t i = 0; i < categories_.size(); i++) {
63 EventType type, 159 base::subtle::NoBarrier_Store(&categories_[i]->enabled_,
Sigurður Ásgeirsson 2011/04/15 17:41:45 better to encapsulate the flag in inline accessors
scheib 2011/04/27 21:20:10 Removed, changed to just a bool.
64 const void* id, 160 static_cast<base::subtle::Atomic32>(1));
65 const std::string& extra, 161 }
66 const char* file, 162 } else {
67 int line) { 163 // Disable all categories.
68 if (!enabled_) 164 for (size_t i = 0; i < categories_.size(); i++) {
Sigurður Ásgeirsson 2011/04/15 17:41:45 copy paste loop, better to copy the test and do pr
scheib 2011/04/27 21:20:10 Done.
165 base::subtle::NoBarrier_Store(&categories_[i]->enabled_,
166 static_cast<base::subtle::Atomic32>(0));
167 }
168 enabled_ = false;
169 FlushWithLockAlreadyHeld();
170 }
171 }
172
173 void TraceLog::SetOutputCallback(TraceLog::OutputCallback* cb) {
174 AutoLock lock(lock_);
175 if (enabled_) {
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: no brackets for an uncomplicated one-line com
scheib 2011/04/27 21:20:10 Done.
176 FlushWithLockAlreadyHeld();
177 }
178 output_callback_.reset(cb);
179 }
180
181 void TraceLog::AddRemotelyCollectedData(const std::string& json_events) {
182 AutoLock lock(lock_);
183 if (output_callback_.get())
184 output_callback_->Run(json_events);
185 }
186
187 void TraceLog::Flush() {
188 AutoLock lock(lock_);
189 FlushWithLockAlreadyHeld();
190 }
191
192 void TraceLog::FlushWithLockAlreadyHeld() {
Sigurður Ásgeirsson 2011/04/15 17:41:45 lock_.AssertAcquired()?
scheib 2011/04/27 21:20:10 Done.
193 if (output_callback_.get() && logged_events_.size()) {
194 for (size_t i = 0; i < logged_events_.size(); i += TRACE_EVENT_BATCH_SIZE) {
195 std::string json_events;
196 TraceEvent::AppendAsJSON(&json_events, logged_events_,
197 i, TRACE_EVENT_BATCH_SIZE);
198 output_callback_->Run(json_events);
Sigurður Ásgeirsson 2011/04/15 17:41:45 I really don't like this - e.g. calling out of mod
scheib 2011/04/27 21:20:10 Done.
199 }
200 }
201 logged_events_.erase(logged_events_.begin(), logged_events_.end());
202 }
203
204 void TraceLog::AddTraceEvent(TraceEventPhase phase,
205 const char* file, int line,
206 TraceCategory* category,
207 const char* name,
208 const char* arg1name, const char* arg1val,
Sigurður Ásgeirsson 2011/04/15 17:41:45 arg1_name, arg1_val, etc
scheib 2011/04/27 21:20:10 Done.
209 const char* arg2name, const char* arg2val) {
210 DCHECK(file && name);
211 #ifdef USE_UNRELIABLE_NOW
212 TimeTicks now = TimeTicks::HighResNow();
213 #else
214 TimeTicks now = TimeTicks::Now();
215 #endif
216 //static_cast<unsigned long>(base::GetCurrentProcId()),
Sigurður Ásgeirsson 2011/04/15 17:41:45 ?
scheib 2011/04/27 21:20:10 Done.
217 AutoLock lock(lock_);
218 if (logged_events_.size() >= TRACE_EVENT_BUFFER_SIZE)
69 return; 219 return;
70 220 logged_events_.push_back(TraceEvent());
71 #ifdef USE_UNRELIABLE_NOW 221 TraceEvent& event = logged_events_.back();
72 TimeTicks tick = TimeTicks::HighResNow(); 222 event.processId = static_cast<unsigned long>(base::GetCurrentProcId());
73 #else 223 event.threadId = PlatformThread::CurrentId();
74 TimeTicks tick = TimeTicks::Now(); 224 event.timestamp = now;
225 event.phase = phase;
226 event.category = category;
227 event.name = name;
228 event.argNames[0] = arg1name;
229 event.argValues[0] = arg1name ? arg1val : "";
230 event.argNames[1] = arg2name;
231 event.argValues[1] = arg2name ? arg2val : "";
232 COMPILE_ASSERT(TRACE_MAX_NUM_ARGS == 2, TraceEvent_arc_count_out_of_sync);
233 }
234
235 void TraceLog::AddTraceEventEtw(TraceEventPhase phase,
236 const char* file, int line,
237 const char* name,
238 const void* id,
239 const char* extra) {
240 // Legacy trace points on windows called to ETW
241 #if defined(OS_WIN)
242 TraceEventETWProvider::Trace(name, phase, id, extra);
75 #endif 243 #endif
76 TimeDelta delta = tick - trace_start_time_; 244
77 int64 usec = delta.InMicroseconds(); 245 // Also add new trace event behavior
78 std::string msg = 246 static TraceCategory* category = GetCategory("ETW Trace Event");
79 StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', " 247 if (category->enabled_) {
80 "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', " 248 AddTraceEvent(phase, file, line, category, name,
81 "'line_number':'%d', 'usec_begin': %" PRId64 "},\n", 249 "id", StringPrintf("%p", id).c_str(),
82 static_cast<unsigned long>(base::GetCurrentProcId()), 250 "extra", extra ? extra : "");
83 static_cast<unsigned long>(PlatformThread::CurrentId()), 251 }
84 kEventTypeNames[type],
85 name.c_str(),
86 id,
87 extra.c_str(),
88 file,
89 line,
90 usec);
91
92 Log(msg);
93 }
94
95 TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
96 base::ProcessHandle proc = base::GetCurrentProcessHandle();
97 #if !defined(OS_MACOSX)
98 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc));
99 #else
100 // The default port provider is sufficient to get data for the current
101 // process.
102 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc,
103 NULL));
104 #endif
105 }
106
107 TraceLog::~TraceLog() {
108 Stop();
109 }
110
111 bool TraceLog::OpenLogFile() {
112 FilePath::StringType pid_filename =
113 StringPrintf(kLogFileName, base::GetCurrentProcId());
114 FilePath log_file_path;
115 if (!PathService::Get(base::DIR_EXE, &log_file_path))
116 return false;
117 log_file_path = log_file_path.Append(pid_filename);
118 log_file_ = file_util::OpenFile(log_file_path, "a");
119 if (!log_file_) {
120 // try the current directory
121 log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
122 if (!log_file_) {
123 return false;
124 }
125 }
126 return true;
127 }
128
129 void TraceLog::CloseLogFile() {
130 if (log_file_) {
131 file_util::CloseFile(log_file_);
132 }
133 }
134
135 bool TraceLog::Start() {
136 if (enabled_)
137 return true;
138 enabled_ = OpenLogFile();
139 if (enabled_) {
140 Log("var raw_trace_events = [\n");
141 trace_start_time_ = TimeTicks::Now();
142 timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
143 }
144 return enabled_;
145 }
146
147 void TraceLog::Stop() {
148 if (enabled_) {
149 enabled_ = false;
150 Log("];\n");
151 CloseLogFile();
152 timer_.Stop();
153 }
154 }
155
156 void TraceLog::Heartbeat() {
157 std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
158 TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
159 }
160
161 void TraceLog::Log(const std::string& msg) {
162 AutoLock lock(file_lock_);
163
164 fprintf(log_file_, "%s", msg.c_str());
165 } 252 }
166 253
167 } // namespace debug 254 } // namespace debug
168 } // namespace base 255 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698