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

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

Issue 1115023003: [Startup Tracing] The TraceConfig class [STALE] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 7 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
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/trace_event/trace_event_impl.h" 5 #include "base/trace_event/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/base_switches.h" 10 #include "base/base_switches.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 54
55 namespace base { 55 namespace base {
56 namespace trace_event { 56 namespace trace_event {
57 57
58 namespace { 58 namespace {
59 59
60 // The overhead of TraceEvent above this threshold will be reported in the 60 // The overhead of TraceEvent above this threshold will be reported in the
61 // trace. 61 // trace.
62 const int kOverheadReportThresholdInMicroseconds = 50; 62 const int kOverheadReportThresholdInMicroseconds = 50;
63 63
64 // String options that can be used to initialize TraceOptions.
65 const char kRecordUntilFull[] = "record-until-full";
66 const char kRecordContinuously[] = "record-continuously";
67 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible";
68 const char kTraceToConsole[] = "trace-to-console";
69 const char kEnableSampling[] = "enable-sampling";
70 const char kEnableSystrace[] = "enable-systrace";
71 const char kEnableArgumentFilter[] = "enable-argument-filter";
72
73 // Controls the number of trace events we will buffer in-memory 64 // Controls the number of trace events we will buffer in-memory
74 // before throwing them away. 65 // before throwing them away.
75 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; 66 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize;
76 const size_t kTraceEventVectorBigBufferChunks = 67 const size_t kTraceEventVectorBigBufferChunks =
77 512000000 / kTraceBufferChunkSize; 68 512000000 / kTraceBufferChunkSize;
78 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; 69 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize;
79 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; 70 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4;
80 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; 71 const size_t kTraceEventBufferSizeInBytes = 100 * 1024;
81 // Can store results for 30 seconds with 1 ms sampling interval. 72 // Can store results for 30 seconds with 1 ms sampling interval.
82 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; 73 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize;
83 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. 74 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
84 const size_t kEchoToConsoleTraceEventBufferChunks = 256; 75 const size_t kEchoToConsoleTraceEventBufferChunks = 256;
85 76
86 const int kThreadFlushTimeoutMs = 3000; 77 const int kThreadFlushTimeoutMs = 3000;
87 78
88 #if !defined(OS_NACL) 79 #if !defined(OS_NACL)
89 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. 80 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575.
90 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; 81 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task";
91 #endif 82 #endif
92 83
93 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY(";
94
95 #define MAX_CATEGORY_GROUPS 100 84 #define MAX_CATEGORY_GROUPS 100
96 85
97 // Parallel arrays g_category_groups and g_category_group_enabled are separate 86 // Parallel arrays g_category_groups and g_category_group_enabled are separate
98 // so that a pointer to a member of g_category_group_enabled can be easily 87 // so that a pointer to a member of g_category_group_enabled can be easily
99 // converted to an index into g_category_groups. This allows macros to deal 88 // converted to an index into g_category_groups. This allows macros to deal
100 // only with char enabled pointers from g_category_group_enabled, and we can 89 // only with char enabled pointers from g_category_group_enabled, and we can
101 // convert internally to determine the category name from the char enabled 90 // convert internally to determine the category name from the char enabled
102 // pointer. 91 // pointer.
103 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { 92 const char* g_category_groups[MAX_CATEGORY_GROUPS] = {
104 "toplevel", 93 "toplevel",
(...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 : bucket(bucket), 972 : bucket(bucket),
984 bucket_name(name), 973 bucket_name(name),
985 callback(callback) { 974 callback(callback) {
986 } 975 }
987 976
988 TraceBucketData::~TraceBucketData() { 977 TraceBucketData::~TraceBucketData() {
989 } 978 }
990 979
991 //////////////////////////////////////////////////////////////////////////////// 980 ////////////////////////////////////////////////////////////////////////////////
992 // 981 //
993 // TraceOptions
994 //
995 ////////////////////////////////////////////////////////////////////////////////
996
997 bool TraceOptions::SetFromString(const std::string& options_string) {
998 record_mode = RECORD_UNTIL_FULL;
999 enable_sampling = false;
1000 enable_systrace = false;
1001
1002 std::vector<std::string> split;
1003 std::vector<std::string>::iterator iter;
1004 base::SplitString(options_string, ',', &split);
1005 for (iter = split.begin(); iter != split.end(); ++iter) {
1006 if (*iter == kRecordUntilFull) {
1007 record_mode = RECORD_UNTIL_FULL;
1008 } else if (*iter == kRecordContinuously) {
1009 record_mode = RECORD_CONTINUOUSLY;
1010 } else if (*iter == kTraceToConsole) {
1011 record_mode = ECHO_TO_CONSOLE;
1012 } else if (*iter == kRecordAsMuchAsPossible) {
1013 record_mode = RECORD_AS_MUCH_AS_POSSIBLE;
1014 } else if (*iter == kEnableSampling) {
1015 enable_sampling = true;
1016 } else if (*iter == kEnableSystrace) {
1017 enable_systrace = true;
1018 } else if (*iter == kEnableArgumentFilter) {
1019 enable_argument_filter = true;
1020 } else {
1021 return false;
1022 }
1023 }
1024 return true;
1025 }
1026
1027 std::string TraceOptions::ToString() const {
1028 std::string ret;
1029 switch (record_mode) {
1030 case RECORD_UNTIL_FULL:
1031 ret = kRecordUntilFull;
1032 break;
1033 case RECORD_CONTINUOUSLY:
1034 ret = kRecordContinuously;
1035 break;
1036 case ECHO_TO_CONSOLE:
1037 ret = kTraceToConsole;
1038 break;
1039 case RECORD_AS_MUCH_AS_POSSIBLE:
1040 ret = kRecordAsMuchAsPossible;
1041 break;
1042 default:
1043 NOTREACHED();
1044 }
1045 if (enable_sampling)
1046 ret = ret + "," + kEnableSampling;
1047 if (enable_systrace)
1048 ret = ret + "," + kEnableSystrace;
1049 if (enable_argument_filter)
1050 ret = ret + "," + kEnableArgumentFilter;
1051 return ret;
1052 }
1053
1054 ////////////////////////////////////////////////////////////////////////////////
1055 //
1056 // TraceLog 982 // TraceLog
1057 // 983 //
1058 //////////////////////////////////////////////////////////////////////////////// 984 ////////////////////////////////////////////////////////////////////////////////
1059 985
1060 class TraceLog::ThreadLocalEventBuffer 986 class TraceLog::ThreadLocalEventBuffer
1061 : public MessageLoop::DestructionObserver { 987 : public MessageLoop::DestructionObserver {
1062 public: 988 public:
1063 ThreadLocalEventBuffer(TraceLog* trace_log); 989 ThreadLocalEventBuffer(TraceLog* trace_log);
1064 ~ThreadLocalEventBuffer() override; 990 ~ThreadLocalEventBuffer() override;
1065 991
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after
2424 } 2350 }
2425 2351
2426 void TraceLog::SetCurrentThreadBlocksMessageLoop() { 2352 void TraceLog::SetCurrentThreadBlocksMessageLoop() {
2427 thread_blocks_message_loop_.Set(true); 2353 thread_blocks_message_loop_.Set(true);
2428 if (thread_local_event_buffer_.Get()) { 2354 if (thread_local_event_buffer_.Get()) {
2429 // This will flush the thread local buffer. 2355 // This will flush the thread local buffer.
2430 delete thread_local_event_buffer_.Get(); 2356 delete thread_local_event_buffer_.Get();
2431 } 2357 }
2432 } 2358 }
2433 2359
2434 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
2435 const std::string& str) {
2436 return str.empty() ||
2437 str.at(0) == ' ' ||
2438 str.at(str.length() - 1) == ' ';
2439 }
2440
2441 CategoryFilter::CategoryFilter(const std::string& filter_string) {
2442 if (!filter_string.empty())
2443 Initialize(filter_string);
2444 else
2445 Initialize(CategoryFilter::kDefaultCategoryFilterString);
2446 }
2447
2448 CategoryFilter::CategoryFilter() {
2449 Initialize(CategoryFilter::kDefaultCategoryFilterString);
2450 }
2451
2452 CategoryFilter::CategoryFilter(const CategoryFilter& cf)
2453 : included_(cf.included_),
2454 disabled_(cf.disabled_),
2455 excluded_(cf.excluded_),
2456 delays_(cf.delays_) {
2457 }
2458
2459 CategoryFilter::~CategoryFilter() {
2460 }
2461
2462 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) {
2463 if (this == &rhs)
2464 return *this;
2465
2466 included_ = rhs.included_;
2467 disabled_ = rhs.disabled_;
2468 excluded_ = rhs.excluded_;
2469 delays_ = rhs.delays_;
2470 return *this;
2471 }
2472
2473 void CategoryFilter::Initialize(const std::string& filter_string) {
2474 // Tokenize list of categories, delimited by ','.
2475 StringTokenizer tokens(filter_string, ",");
2476 // Add each token to the appropriate list (included_,excluded_).
2477 while (tokens.GetNext()) {
2478 std::string category = tokens.token();
2479 // Ignore empty categories.
2480 if (category.empty())
2481 continue;
2482 // Synthetic delays are of the form 'DELAY(delay;option;option;...)'.
2483 if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 &&
2484 category.at(category.size() - 1) == ')') {
2485 category = category.substr(
2486 strlen(kSyntheticDelayCategoryFilterPrefix),
2487 category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1);
2488 size_t name_length = category.find(';');
2489 if (name_length != std::string::npos && name_length > 0 &&
2490 name_length != category.size() - 1) {
2491 delays_.push_back(category);
2492 }
2493 } else if (category.at(0) == '-') {
2494 // Excluded categories start with '-'.
2495 // Remove '-' from category string.
2496 category = category.substr(1);
2497 excluded_.push_back(category);
2498 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")),
2499 TRACE_DISABLED_BY_DEFAULT("")) == 0) {
2500 disabled_.push_back(category);
2501 } else {
2502 included_.push_back(category);
2503 }
2504 }
2505 }
2506
2507 void CategoryFilter::WriteString(const StringList& values,
2508 std::string* out,
2509 bool included) const {
2510 bool prepend_comma = !out->empty();
2511 int token_cnt = 0;
2512 for (StringList::const_iterator ci = values.begin();
2513 ci != values.end(); ++ci) {
2514 if (token_cnt > 0 || prepend_comma)
2515 StringAppendF(out, ",");
2516 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
2517 ++token_cnt;
2518 }
2519 }
2520
2521 void CategoryFilter::WriteString(const StringList& delays,
2522 std::string* out) const {
2523 bool prepend_comma = !out->empty();
2524 int token_cnt = 0;
2525 for (StringList::const_iterator ci = delays.begin();
2526 ci != delays.end(); ++ci) {
2527 if (token_cnt > 0 || prepend_comma)
2528 StringAppendF(out, ",");
2529 StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix,
2530 ci->c_str());
2531 ++token_cnt;
2532 }
2533 }
2534
2535 std::string CategoryFilter::ToString() const {
2536 std::string filter_string;
2537 WriteString(included_, &filter_string, true);
2538 WriteString(disabled_, &filter_string, true);
2539 WriteString(excluded_, &filter_string, false);
2540 WriteString(delays_, &filter_string);
2541 return filter_string;
2542 }
2543
2544 bool CategoryFilter::IsCategoryGroupEnabled(
2545 const char* category_group_name) const {
2546 // TraceLog should call this method only as part of enabling/disabling
2547 // categories.
2548
2549 bool had_enabled_by_default = false;
2550 DCHECK(category_group_name);
2551 CStringTokenizer category_group_tokens(
2552 category_group_name, category_group_name + strlen(category_group_name),
2553 ",");
2554 while (category_group_tokens.GetNext()) {
2555 std::string category_group_token = category_group_tokens.token();
2556 // Don't allow empty tokens, nor tokens with leading or trailing space.
2557 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
2558 category_group_token))
2559 << "Disallowed category string";
2560 if (IsCategoryEnabled(category_group_token.c_str())) {
2561 return true;
2562 }
2563 if (!MatchPattern(category_group_token.c_str(),
2564 TRACE_DISABLED_BY_DEFAULT("*")))
2565 had_enabled_by_default = true;
2566 }
2567 // Do a second pass to check for explicitly disabled categories
2568 // (those explicitly enabled have priority due to first pass).
2569 category_group_tokens.Reset();
2570 bool category_group_disabled = false;
2571 while (category_group_tokens.GetNext()) {
2572 std::string category_group_token = category_group_tokens.token();
2573 for (StringList::const_iterator ci = excluded_.begin();
2574 ci != excluded_.end(); ++ci) {
2575 if (MatchPattern(category_group_token.c_str(), ci->c_str())) {
2576 // Current token of category_group_name is present in excluded_list.
2577 // Flag the exclusion and proceed further to check if any of the
2578 // remaining categories of category_group_name is not present in the
2579 // excluded_ list.
2580 category_group_disabled = true;
2581 break;
2582 }
2583 // One of the category of category_group_name is not present in
2584 // excluded_ list. So, it has to be included_ list. Enable the
2585 // category_group_name for recording.
2586 category_group_disabled = false;
2587 }
2588 // One of the categories present in category_group_name is not present in
2589 // excluded_ list. Implies this category_group_name group can be enabled
2590 // for recording, since one of its groups is enabled for recording.
2591 if (!category_group_disabled)
2592 break;
2593 }
2594 // If the category group is not excluded, and there are no included patterns
2595 // we consider this category group enabled, as long as it had categories
2596 // other than disabled-by-default.
2597 return !category_group_disabled &&
2598 included_.empty() && had_enabled_by_default;
2599 }
2600
2601 bool CategoryFilter::IsCategoryEnabled(const char* category_name) const {
2602 StringList::const_iterator ci;
2603
2604 // Check the disabled- filters and the disabled-* wildcard first so that a
2605 // "*" filter does not include the disabled.
2606 for (ci = disabled_.begin(); ci != disabled_.end(); ++ci) {
2607 if (MatchPattern(category_name, ci->c_str()))
2608 return true;
2609 }
2610
2611 if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*")))
2612 return false;
2613
2614 for (ci = included_.begin(); ci != included_.end(); ++ci) {
2615 if (MatchPattern(category_name, ci->c_str()))
2616 return true;
2617 }
2618
2619 return false;
2620 }
2621
2622 bool CategoryFilter::HasIncludedPatterns() const {
2623 return !included_.empty();
2624 }
2625
2626 void CategoryFilter::Merge(const CategoryFilter& nested_filter) {
2627 // Keep included patterns only if both filters have an included entry.
2628 // Otherwise, one of the filter was specifying "*" and we want to honour the
2629 // broadest filter.
2630 if (HasIncludedPatterns() && nested_filter.HasIncludedPatterns()) {
2631 included_.insert(included_.end(),
2632 nested_filter.included_.begin(),
2633 nested_filter.included_.end());
2634 } else {
2635 included_.clear();
2636 }
2637
2638 disabled_.insert(disabled_.end(),
2639 nested_filter.disabled_.begin(),
2640 nested_filter.disabled_.end());
2641 excluded_.insert(excluded_.end(),
2642 nested_filter.excluded_.begin(),
2643 nested_filter.excluded_.end());
2644 delays_.insert(delays_.end(),
2645 nested_filter.delays_.begin(),
2646 nested_filter.delays_.end());
2647 }
2648
2649 void CategoryFilter::Clear() {
2650 included_.clear();
2651 disabled_.clear();
2652 excluded_.clear();
2653 }
2654
2655 const CategoryFilter::StringList&
2656 CategoryFilter::GetSyntheticDelayValues() const {
2657 return delays_;
2658 }
2659
2660 } // namespace trace_event 2360 } // namespace trace_event
2661 } // namespace base 2361 } // namespace base
2662 2362
2663 namespace trace_event_internal { 2363 namespace trace_event_internal {
2664 2364
2665 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( 2365 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
2666 const char* category_group, const char* name) { 2366 const char* category_group, const char* name) {
2667 // The single atom works because for now the category_group can only be "gpu". 2367 // The single atom works because for now the category_group can only be "gpu".
2668 DCHECK_EQ(strcmp(category_group, "gpu"), 0); 2368 DCHECK_EQ(strcmp(category_group, "gpu"), 0);
2669 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; 2369 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0;
(...skipping 12 matching lines...) Expand all
2682 } 2382 }
2683 2383
2684 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { 2384 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
2685 if (*category_group_enabled_) { 2385 if (*category_group_enabled_) {
2686 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, 2386 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_,
2687 name_, event_handle_); 2387 name_, event_handle_);
2688 } 2388 }
2689 } 2389 }
2690 2390
2691 } // namespace trace_event_internal 2391 } // namespace trace_event_internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698