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

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

Issue 109933006: Implement sampling profiler (chromium side change) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | chrome/browser/lifetime/application_lifetime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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_impl.h" 5 #include "base/debug/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base_switches.h" 9 #include "base/base_switches.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { 1087 void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() {
1088 delete this; 1088 delete this;
1089 } 1089 }
1090 1090
1091 void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() { 1091 void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {
1092 if (!chunk_) 1092 if (!chunk_)
1093 return; 1093 return;
1094 1094
1095 trace_log_->lock_.AssertAcquired(); 1095 trace_log_->lock_.AssertAcquired();
1096 if (trace_log_->CheckGeneration(generation_)) { 1096 if (trace_log_->CheckGeneration(generation_)) {
1097 // Return the chunk to the buffer only if the generation matches, 1097 // Return the chunk to the buffer only if the generation matches.
1098 trace_log_->logged_events_->ReturnChunk(chunk_index_, chunk_.Pass()); 1098 trace_log_->logged_events_->ReturnChunk(chunk_index_, chunk_.Pass());
1099 } 1099 }
1100 // Otherwise this method may be called from the destructor, or TraceLog will 1100 // Otherwise this method may be called from the destructor, or TraceLog will
1101 // find the generation mismatch and delete this buffer soon. 1101 // find the generation mismatch and delete this buffer soon.
1102 } 1102 }
1103 1103
1104 // static 1104 // static
1105 TraceLog* TraceLog::GetInstance() { 1105 TraceLog* TraceLog::GetInstance() {
1106 return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get(); 1106 return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get();
1107 } 1107 }
1108 1108
1109 TraceLog::TraceLog() 1109 TraceLog::TraceLog()
1110 : enabled_(false), 1110 : mode_(DISABLED),
1111 num_traces_recorded_(0), 1111 num_traces_recorded_(0),
1112 event_callback_(0), 1112 event_callback_(0),
1113 dispatching_to_observer_list_(false), 1113 dispatching_to_observer_list_(false),
1114 process_sort_index_(0), 1114 process_sort_index_(0),
1115 process_id_hash_(0), 1115 process_id_hash_(0),
1116 process_id_(0), 1116 process_id_(0),
1117 watch_category_(0), 1117 watch_category_(0),
1118 trace_options_(RECORD_UNTIL_FULL), 1118 trace_options_(RECORD_UNTIL_FULL),
1119 sampling_thread_handle_(0), 1119 sampling_thread_handle_(0),
1120 category_filter_(CategoryFilter::kDefaultCategoryFilterString), 1120 category_filter_(CategoryFilter::kDefaultCategoryFilterString),
(...skipping 25 matching lines...) Expand all
1146 switches::kTraceToConsole); 1146 switches::kTraceToConsole);
1147 if (filter.empty()) { 1147 if (filter.empty()) {
1148 filter = kEchoToConsoleCategoryFilter; 1148 filter = kEchoToConsoleCategoryFilter;
1149 } else { 1149 } else {
1150 filter.append(","); 1150 filter.append(",");
1151 filter.append(kEchoToConsoleCategoryFilter); 1151 filter.append(kEchoToConsoleCategoryFilter);
1152 } 1152 }
1153 1153
1154 LOG(ERROR) << "Start " << switches::kTraceToConsole 1154 LOG(ERROR) << "Start " << switches::kTraceToConsole
1155 << " with CategoryFilter '" << filter << "'."; 1155 << " with CategoryFilter '" << filter << "'.";
1156 SetEnabled(CategoryFilter(filter), ECHO_TO_CONSOLE); 1156 SetEnabled(CategoryFilter(filter), RECORDING_MODE, ECHO_TO_CONSOLE);
1157 } 1157 }
1158 #endif 1158 #endif
1159 1159
1160 logged_events_.reset(CreateTraceBuffer()); 1160 logged_events_.reset(CreateTraceBuffer());
1161 } 1161 }
1162 1162
1163 TraceLog::~TraceLog() { 1163 TraceLog::~TraceLog() {
1164 } 1164 }
1165 1165
1166 const unsigned char* TraceLog::GetCategoryGroupEnabled( 1166 const unsigned char* TraceLog::GetCategoryGroupEnabled(
(...skipping 18 matching lines...) Expand all
1185 g_category_group_enabled + MAX_CATEGORY_GROUPS)) << 1185 g_category_group_enabled + MAX_CATEGORY_GROUPS)) <<
1186 "out of bounds category pointer"; 1186 "out of bounds category pointer";
1187 uintptr_t category_index = 1187 uintptr_t category_index =
1188 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); 1188 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]);
1189 return g_category_groups[category_index]; 1189 return g_category_groups[category_index];
1190 } 1190 }
1191 1191
1192 void TraceLog::UpdateCategoryGroupEnabledFlag(int category_index) { 1192 void TraceLog::UpdateCategoryGroupEnabledFlag(int category_index) {
1193 unsigned char enabled_flag = 0; 1193 unsigned char enabled_flag = 0;
1194 const char* category_group = g_category_groups[category_index]; 1194 const char* category_group = g_category_groups[category_index];
1195 if (enabled_ && category_filter_.IsCategoryGroupEnabled(category_group)) 1195 if (mode_ == RECORDING_MODE &&
1196 category_filter_.IsCategoryGroupEnabled(category_group))
1196 enabled_flag |= ENABLED_FOR_RECORDING; 1197 enabled_flag |= ENABLED_FOR_RECORDING;
1198 if (mode_ == MONITORING_MODE &&
1199 category_filter_.IsCategoryGroupEnabled(category_group))
1200 enabled_flag |= ENABLED_FOR_MONITORING;
1197 if (event_callback_ && 1201 if (event_callback_ &&
1198 event_callback_category_filter_.IsCategoryGroupEnabled(category_group)) 1202 event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
1199 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; 1203 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
1200 g_category_group_enabled[category_index] = enabled_flag; 1204 g_category_group_enabled[category_index] = enabled_flag;
1201 } 1205 }
1202 1206
1203 void TraceLog::UpdateCategoryGroupEnabledFlags() { 1207 void TraceLog::UpdateCategoryGroupEnabledFlags() {
1204 for (int i = 0; i < g_category_index; i++) 1208 for (int i = 0; i < g_category_index; i++)
1205 UpdateCategoryGroupEnabledFlag(i); 1209 UpdateCategoryGroupEnabledFlag(i);
1206 } 1210 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 void TraceLog::GetKnownCategoryGroups( 1253 void TraceLog::GetKnownCategoryGroups(
1250 std::vector<std::string>* category_groups) { 1254 std::vector<std::string>* category_groups) {
1251 AutoLock lock(lock_); 1255 AutoLock lock(lock_);
1252 category_groups->push_back( 1256 category_groups->push_back(
1253 g_category_groups[g_category_trace_event_overhead]); 1257 g_category_groups[g_category_trace_event_overhead]);
1254 for (int i = g_num_builtin_categories; i < g_category_index; i++) 1258 for (int i = g_num_builtin_categories; i < g_category_index; i++)
1255 category_groups->push_back(g_category_groups[i]); 1259 category_groups->push_back(g_category_groups[i]);
1256 } 1260 }
1257 1261
1258 void TraceLog::SetEnabled(const CategoryFilter& category_filter, 1262 void TraceLog::SetEnabled(const CategoryFilter& category_filter,
1263 Mode mode,
1259 Options options) { 1264 Options options) {
1260 std::vector<EnabledStateObserver*> observer_list; 1265 std::vector<EnabledStateObserver*> observer_list;
1261 { 1266 {
1262 AutoLock lock(lock_); 1267 AutoLock lock(lock_);
1263 1268
1264 // Can't enable tracing when Flush() is in progress. 1269 // Can't enable tracing when Flush() is in progress.
1265 DCHECK(!flush_message_loop_proxy_.get()); 1270 DCHECK(!flush_message_loop_proxy_.get());
1266 1271
1267 Options old_options = trace_options(); 1272 Options old_options = trace_options();
1268 1273
1269 if (enabled_) { 1274 if (IsEnabled()) {
1270 if (options != old_options) { 1275 if (options != old_options) {
1271 DLOG(ERROR) << "Attemting to re-enable tracing with a different " 1276 DLOG(ERROR) << "Attemting to re-enable tracing with a different "
1272 << "set of options."; 1277 << "set of options.";
1273 } 1278 }
1274 1279
1275 category_filter_.Merge(category_filter); 1280 category_filter_.Merge(category_filter);
1276 UpdateCategoryGroupEnabledFlags(); 1281 UpdateCategoryGroupEnabledFlags();
1277 return; 1282 return;
1278 } 1283 }
1279 1284
1280 if (dispatching_to_observer_list_) { 1285 if (dispatching_to_observer_list_) {
1281 DLOG(ERROR) << 1286 DLOG(ERROR) <<
1282 "Cannot manipulate TraceLog::Enabled state from an observer."; 1287 "Cannot manipulate TraceLog::Enabled state from an observer.";
1283 return; 1288 return;
1284 } 1289 }
1285 1290
1286 enabled_ = true; 1291 mode_ = mode;
1287 1292
1288 if (options != old_options) { 1293 if (options != old_options) {
1289 subtle::NoBarrier_Store(&trace_options_, options); 1294 subtle::NoBarrier_Store(&trace_options_, options);
1290 UseNextTraceBuffer(); 1295 UseNextTraceBuffer();
1291 } 1296 }
1292 1297
1293 num_traces_recorded_++; 1298 num_traces_recorded_++;
1294 1299
1295 category_filter_ = CategoryFilter(category_filter); 1300 category_filter_ = CategoryFilter(category_filter);
1296 UpdateCategoryGroupEnabledFlags(); 1301 UpdateCategoryGroupEnabledFlags();
1297 1302
1298 if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { 1303 if (options & ENABLE_SAMPLING) {
1299 sampling_thread_.reset(new TraceSamplingThread); 1304 sampling_thread_.reset(new TraceSamplingThread);
1300 sampling_thread_->RegisterSampleBucket( 1305 sampling_thread_->RegisterSampleBucket(
1301 &g_trace_state[0], 1306 &g_trace_state[0],
1302 "bucket0", 1307 "bucket0",
1303 Bind(&TraceSamplingThread::DefaultSamplingCallback)); 1308 Bind(&TraceSamplingThread::DefaultSamplingCallback));
1304 sampling_thread_->RegisterSampleBucket( 1309 sampling_thread_->RegisterSampleBucket(
1305 &g_trace_state[1], 1310 &g_trace_state[1],
1306 "bucket1", 1311 "bucket1",
1307 Bind(&TraceSamplingThread::DefaultSamplingCallback)); 1312 Bind(&TraceSamplingThread::DefaultSamplingCallback));
1308 sampling_thread_->RegisterSampleBucket( 1313 sampling_thread_->RegisterSampleBucket(
(...skipping 25 matching lines...) Expand all
1334 } 1339 }
1335 1340
1336 void TraceLog::SetDisabled() { 1341 void TraceLog::SetDisabled() {
1337 AutoLock lock(lock_); 1342 AutoLock lock(lock_);
1338 SetDisabledWhileLocked(); 1343 SetDisabledWhileLocked();
1339 } 1344 }
1340 1345
1341 void TraceLog::SetDisabledWhileLocked() { 1346 void TraceLog::SetDisabledWhileLocked() {
1342 lock_.AssertAcquired(); 1347 lock_.AssertAcquired();
1343 1348
1344 if (!enabled_) 1349 if (!IsEnabled())
1345 return; 1350 return;
1346 1351
1347 if (dispatching_to_observer_list_) { 1352 if (dispatching_to_observer_list_) {
1348 DLOG(ERROR) 1353 DLOG(ERROR)
1349 << "Cannot manipulate TraceLog::Enabled state from an observer."; 1354 << "Cannot manipulate TraceLog::Enabled state from an observer.";
1350 return; 1355 return;
1351 } 1356 }
1352 1357
1353 enabled_ = false; 1358 mode_ = DISABLED;
1354 1359
1355 if (sampling_thread_.get()) { 1360 if (sampling_thread_.get()) {
1356 // Stop the sampling thread. 1361 // Stop the sampling thread.
1357 sampling_thread_->Stop(); 1362 sampling_thread_->Stop();
1358 lock_.Release(); 1363 lock_.Release();
1359 PlatformThread::Join(sampling_thread_handle_); 1364 PlatformThread::Join(sampling_thread_handle_);
1360 lock_.Acquire(); 1365 lock_.Acquire();
1361 sampling_thread_handle_ = PlatformThreadHandle(); 1366 sampling_thread_handle_ = PlatformThreadHandle();
1362 sampling_thread_.reset(); 1367 sampling_thread_.reset();
1363 } 1368 }
(...skipping 13 matching lines...) Expand all
1377 // trace event. 1382 // trace event.
1378 AutoUnlock unlock(lock_); 1383 AutoUnlock unlock(lock_);
1379 for (size_t i = 0; i < observer_list.size(); ++i) 1384 for (size_t i = 0; i < observer_list.size(); ++i)
1380 observer_list[i]->OnTraceLogDisabled(); 1385 observer_list[i]->OnTraceLogDisabled();
1381 } 1386 }
1382 dispatching_to_observer_list_ = false; 1387 dispatching_to_observer_list_ = false;
1383 } 1388 }
1384 1389
1385 int TraceLog::GetNumTracesRecorded() { 1390 int TraceLog::GetNumTracesRecorded() {
1386 AutoLock lock(lock_); 1391 AutoLock lock(lock_);
1387 if (!enabled_) 1392 if (!IsEnabled())
1388 return -1; 1393 return -1;
1389 return num_traces_recorded_; 1394 return num_traces_recorded_;
1390 } 1395 }
1391 1396
1392 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { 1397 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {
1393 enabled_state_observer_list_.push_back(listener); 1398 enabled_state_observer_list_.push_back(listener);
1394 } 1399 }
1395 1400
1396 void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) { 1401 void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
1397 std::vector<EnabledStateObserver*>::iterator it = 1402 std::vector<EnabledStateObserver*>::iterator it =
(...skipping 20 matching lines...) Expand all
1418 1423
1419 bool TraceLog::BufferIsFull() const { 1424 bool TraceLog::BufferIsFull() const {
1420 AutoLock lock(lock_); 1425 AutoLock lock(lock_);
1421 return logged_events_->IsFull(); 1426 return logged_events_->IsFull();
1422 } 1427 }
1423 1428
1424 TraceBuffer* TraceLog::CreateTraceBuffer() { 1429 TraceBuffer* TraceLog::CreateTraceBuffer() {
1425 Options options = trace_options(); 1430 Options options = trace_options();
1426 if (options & RECORD_CONTINUOUSLY) 1431 if (options & RECORD_CONTINUOUSLY)
1427 return new TraceBufferRingBuffer(kTraceEventRingBufferChunks); 1432 return new TraceBufferRingBuffer(kTraceEventRingBufferChunks);
1428 else if (options & MONITOR_SAMPLING) 1433 else if ((options & ENABLE_SAMPLING) && mode_ == MONITORING_MODE)
1429 return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks); 1434 return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks);
1430 else if (options & ECHO_TO_CONSOLE) 1435 else if (options & ECHO_TO_CONSOLE)
1431 return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks); 1436 return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks);
1432 return new TraceBufferVector(); 1437 return new TraceBufferVector();
1433 } 1438 }
1434 1439
1435 TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( 1440 TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
1436 TraceEventHandle* handle, bool check_buffer_is_full) { 1441 TraceEventHandle* handle, bool check_buffer_is_full) {
1437 lock_.AssertAcquired(); 1442 lock_.AssertAcquired();
1438 1443
1439 if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) { 1444 if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) {
1445 // Return the chunk to the buffer only if the generation matches.
1440 logged_events_->ReturnChunk(thread_shared_chunk_index_, 1446 logged_events_->ReturnChunk(thread_shared_chunk_index_,
1441 thread_shared_chunk_.Pass()); 1447 thread_shared_chunk_.Pass());
1442 } 1448 }
1443 1449
1444 if (!thread_shared_chunk_) { 1450 if (!thread_shared_chunk_) {
1445 thread_shared_chunk_ = logged_events_->GetChunk( 1451 thread_shared_chunk_ = logged_events_->GetChunk(
1446 &thread_shared_chunk_index_); 1452 &thread_shared_chunk_index_);
1447 if (check_buffer_is_full) 1453 if (check_buffer_is_full)
1448 CheckIfBufferIsFullWhileLocked(); 1454 CheckIfBufferIsFullWhileLocked();
1449 } 1455 }
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 unsigned long long id, 1692 unsigned long long id,
1687 int thread_id, 1693 int thread_id,
1688 const TimeTicks& timestamp, 1694 const TimeTicks& timestamp,
1689 int num_args, 1695 int num_args,
1690 const char** arg_names, 1696 const char** arg_names,
1691 const unsigned char* arg_types, 1697 const unsigned char* arg_types,
1692 const unsigned long long* arg_values, 1698 const unsigned long long* arg_values,
1693 const scoped_refptr<ConvertableToTraceFormat>* convertable_values, 1699 const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
1694 unsigned char flags) { 1700 unsigned char flags) {
1695 TraceEventHandle handle = { 0, 0, 0 }; 1701 TraceEventHandle handle = { 0, 0, 0 };
1702
1696 if (!*category_group_enabled) 1703 if (!*category_group_enabled)
1697 return handle; 1704 return handle;
1698 1705
1699 // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when 1706 // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when
1700 // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) -> 1707 // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) ->
1701 // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ... 1708 // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ...
1702 if (thread_is_in_trace_event_.Get()) 1709 if (thread_is_in_trace_event_.Get())
1703 return handle; 1710 return handle;
1704 1711
1705 AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_); 1712 AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 if (!found) { 1769 if (!found) {
1763 if (existing_names.size()) 1770 if (existing_names.size())
1764 existing_name->second.push_back(','); 1771 existing_name->second.push_back(',');
1765 existing_name->second.append(new_name); 1772 existing_name->second.append(new_name);
1766 } 1773 }
1767 } 1774 }
1768 } 1775 }
1769 } 1776 }
1770 1777
1771 std::string console_message; 1778 std::string console_message;
1772 if ((*category_group_enabled & ENABLED_FOR_RECORDING)) { 1779 if ((mode_ == RECORDING_MODE &&
1780 *category_group_enabled & ENABLED_FOR_RECORDING) ||
1781 (mode_ == MONITORING_MODE &&
1782 *category_group_enabled & ENABLED_FOR_MONITORING) &&
1783 phase == TRACE_EVENT_PHASE_SAMPLE) {
haraken 2013/12/18 21:48:10 Concern 1: There is a threading race in mode_. mod
Xianzhu 2013/12/18 22:26:54 I think we can omit checking mode_ here because we
haraken 2013/12/18 22:40:21 Would you elaborate on how to do that? (1) TRACE_
1773 OptionalAutoLock lock(lock_); 1784 OptionalAutoLock lock(lock_);
1774 1785
1775 TraceEvent* trace_event = NULL; 1786 TraceEvent* trace_event = NULL;
1776 if (thread_local_event_buffer) { 1787 if (thread_local_event_buffer) {
1777 trace_event = thread_local_event_buffer->AddTraceEvent(&handle); 1788 trace_event = thread_local_event_buffer->AddTraceEvent(&handle);
1778 } else { 1789 } else {
1779 lock.EnsureAcquired(); 1790 lock.EnsureAcquired();
1780 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); 1791 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true);
1781 } 1792 }
1782 1793
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 } 2323 }
2313 2324
2314 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { 2325 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
2315 if (*category_group_enabled_) { 2326 if (*category_group_enabled_) {
2316 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, 2327 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_,
2317 name_, event_handle_); 2328 name_, event_handle_);
2318 } 2329 }
2319 } 2330 }
2320 2331
2321 } // namespace trace_event_internal 2332 } // namespace trace_event_internal
OLDNEW
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | chrome/browser/lifetime/application_lifetime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698