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

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

Issue 98953002: Configure synthetic delays through TraceLog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed test failure on ios_dbg_simulator Created 6 years, 11 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
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_synthetic_delay.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"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/debug/leak_annotations.h" 12 #include "base/debug/leak_annotations.h"
13 #include "base/debug/trace_event.h" 13 #include "base/debug/trace_event.h"
14 #include "base/debug/trace_event_synthetic_delay.h"
14 #include "base/format_macros.h" 15 #include "base/format_macros.h"
15 #include "base/json/string_escape.h" 16 #include "base/json/string_escape.h"
16 #include "base/lazy_instance.h" 17 #include "base/lazy_instance.h"
17 #include "base/memory/singleton.h" 18 #include "base/memory/singleton.h"
18 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
19 #include "base/process/process_metrics.h" 20 #include "base/process/process_metrics.h"
20 #include "base/stl_util.h" 21 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_split.h" 23 #include "base/strings/string_split.h"
23 #include "base/strings/string_tokenizer.h" 24 #include "base/strings/string_tokenizer.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 // Can store results for 30 seconds with 1 ms sampling interval. 66 // Can store results for 30 seconds with 1 ms sampling interval.
66 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; 67 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize;
67 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. 68 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
68 const size_t kEchoToConsoleTraceEventBufferChunks = 256; 69 const size_t kEchoToConsoleTraceEventBufferChunks = 256;
69 70
70 const int kThreadFlushTimeoutMs = 3000; 71 const int kThreadFlushTimeoutMs = 3000;
71 72
72 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. 73 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575.
73 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; 74 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task";
74 75
76 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY(";
77
75 #define MAX_CATEGORY_GROUPS 100 78 #define MAX_CATEGORY_GROUPS 100
76 79
77 // Parallel arrays g_category_groups and g_category_group_enabled are separate 80 // Parallel arrays g_category_groups and g_category_group_enabled are separate
78 // so that a pointer to a member of g_category_group_enabled can be easily 81 // so that a pointer to a member of g_category_group_enabled can be easily
79 // converted to an index into g_category_groups. This allows macros to deal 82 // converted to an index into g_category_groups. This allows macros to deal
80 // only with char enabled pointers from g_category_group_enabled, and we can 83 // only with char enabled pointers from g_category_group_enabled, and we can
81 // convert internally to determine the category name from the char enabled 84 // convert internally to determine the category name from the char enabled
82 // pointer. 85 // pointer.
83 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { 86 const char* g_category_groups[MAX_CATEGORY_GROUPS] = {
84 "tracing already shutdown", 87 "tracing already shutdown",
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 event_callback_category_filter_.IsCategoryGroupEnabled(category_group)) 1205 event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
1203 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; 1206 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
1204 g_category_group_enabled[category_index] = enabled_flag; 1207 g_category_group_enabled[category_index] = enabled_flag;
1205 } 1208 }
1206 1209
1207 void TraceLog::UpdateCategoryGroupEnabledFlags() { 1210 void TraceLog::UpdateCategoryGroupEnabledFlags() {
1208 for (int i = 0; i < g_category_index; i++) 1211 for (int i = 0; i < g_category_index; i++)
1209 UpdateCategoryGroupEnabledFlag(i); 1212 UpdateCategoryGroupEnabledFlag(i);
1210 } 1213 }
1211 1214
1215 void TraceLog::UpdateSyntheticDelaysFromCategoryFilter() {
1216 ResetTraceEventSyntheticDelays();
1217 const CategoryFilter::DelayValueList& delays =
1218 category_filter_.GetSyntheticDelayValues();
1219 CategoryFilter::DelayValueList::const_iterator ci;
1220 for (ci = delays.begin(); ci != delays.end(); ++ci) {
1221 TraceEventSyntheticDelay* delay =
1222 TraceEventSyntheticDelay::Lookup(ci->first);
1223 StringTokenizer tokens(ci->second, ";");
1224 while (tokens.GetNext()) {
1225 double target_duration;
1226 if (StringToDouble(tokens.token(), &target_duration)) {
1227 delay->SetTargetDuration(
1228 TimeDelta::FromMicroseconds(target_duration * 1e6));
1229 } else if (tokens.token() == "static") {
1230 delay->SetMode(TraceEventSyntheticDelay::STATIC);
1231 } else if (tokens.token() == "oneshot") {
1232 delay->SetMode(TraceEventSyntheticDelay::ONE_SHOT);
1233 } else if (tokens.token() == "alternating") {
1234 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING);
1235 }
1236 }
1237 }
1238 }
1239
1212 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( 1240 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
1213 const char* category_group) { 1241 const char* category_group) {
1214 DCHECK(!strchr(category_group, '"')) << 1242 DCHECK(!strchr(category_group, '"')) <<
1215 "Category groups may not contain double quote"; 1243 "Category groups may not contain double quote";
1216 AutoLock lock(lock_); 1244 AutoLock lock(lock_);
1217 1245
1218 unsigned char* category_group_enabled = NULL; 1246 unsigned char* category_group_enabled = NULL;
1219 // Search for pre-existing category group. 1247 // Search for pre-existing category group.
1220 for (int i = 0; i < g_category_index; i++) { 1248 for (int i = 0; i < g_category_index; i++) {
1221 if (strcmp(g_category_groups[i], category_group) == 0) { 1249 if (strcmp(g_category_groups[i], category_group) == 0) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 1324
1297 if (options != old_options) { 1325 if (options != old_options) {
1298 subtle::NoBarrier_Store(&trace_options_, options); 1326 subtle::NoBarrier_Store(&trace_options_, options);
1299 UseNextTraceBuffer(); 1327 UseNextTraceBuffer();
1300 } 1328 }
1301 1329
1302 num_traces_recorded_++; 1330 num_traces_recorded_++;
1303 1331
1304 category_filter_ = CategoryFilter(category_filter); 1332 category_filter_ = CategoryFilter(category_filter);
1305 UpdateCategoryGroupEnabledFlags(); 1333 UpdateCategoryGroupEnabledFlags();
1334 UpdateSyntheticDelaysFromCategoryFilter();
1306 1335
1307 if (options & ENABLE_SAMPLING) { 1336 if (options & ENABLE_SAMPLING) {
1308 sampling_thread_.reset(new TraceSamplingThread); 1337 sampling_thread_.reset(new TraceSamplingThread);
1309 sampling_thread_->RegisterSampleBucket( 1338 sampling_thread_->RegisterSampleBucket(
1310 &g_trace_state[0], 1339 &g_trace_state[0],
1311 "bucket0", 1340 "bucket0",
1312 Bind(&TraceSamplingThread::DefaultSamplingCallback)); 1341 Bind(&TraceSamplingThread::DefaultSamplingCallback));
1313 sampling_thread_->RegisterSampleBucket( 1342 sampling_thread_->RegisterSampleBucket(
1314 &g_trace_state[1], 1343 &g_trace_state[1],
1315 "bucket1", 1344 "bucket1",
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 CategoryFilter::CategoryFilter(const std::string& filter_string) { 2198 CategoryFilter::CategoryFilter(const std::string& filter_string) {
2170 if (!filter_string.empty()) 2199 if (!filter_string.empty())
2171 Initialize(filter_string); 2200 Initialize(filter_string);
2172 else 2201 else
2173 Initialize(CategoryFilter::kDefaultCategoryFilterString); 2202 Initialize(CategoryFilter::kDefaultCategoryFilterString);
2174 } 2203 }
2175 2204
2176 CategoryFilter::CategoryFilter(const CategoryFilter& cf) 2205 CategoryFilter::CategoryFilter(const CategoryFilter& cf)
2177 : included_(cf.included_), 2206 : included_(cf.included_),
2178 disabled_(cf.disabled_), 2207 disabled_(cf.disabled_),
2179 excluded_(cf.excluded_) { 2208 excluded_(cf.excluded_),
2209 delays_(cf.delays_) {
2180 } 2210 }
2181 2211
2182 CategoryFilter::~CategoryFilter() { 2212 CategoryFilter::~CategoryFilter() {
2183 } 2213 }
2184 2214
2185 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { 2215 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) {
2186 if (this == &rhs) 2216 if (this == &rhs)
2187 return *this; 2217 return *this;
2188 2218
2189 included_ = rhs.included_; 2219 included_ = rhs.included_;
2190 disabled_ = rhs.disabled_; 2220 disabled_ = rhs.disabled_;
2191 excluded_ = rhs.excluded_; 2221 excluded_ = rhs.excluded_;
2222 delays_ = rhs.delays_;
2192 return *this; 2223 return *this;
2193 } 2224 }
2194 2225
2195 void CategoryFilter::Initialize(const std::string& filter_string) { 2226 void CategoryFilter::Initialize(const std::string& filter_string) {
2196 // Tokenize list of categories, delimited by ','. 2227 // Tokenize list of categories, delimited by ','.
2197 StringTokenizer tokens(filter_string, ","); 2228 StringTokenizer tokens(filter_string, ",");
2198 // Add each token to the appropriate list (included_,excluded_). 2229 // Add each token to the appropriate list (included_,excluded_).
2199 while (tokens.GetNext()) { 2230 while (tokens.GetNext()) {
2200 std::string category = tokens.token(); 2231 std::string category = tokens.token();
2201 // Ignore empty categories. 2232 // Ignore empty categories.
2202 if (category.empty()) 2233 if (category.empty())
2203 continue; 2234 continue;
2204 // Excluded categories start with '-'. 2235 // Synthetic delays are of the form 'DELAY(delay;option;option;...)'.
2205 if (category.at(0) == '-') { 2236 if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 &&
2237 category.at(category.size() - 1) == ')') {
2238 category = category.substr(
2239 strlen(kSyntheticDelayCategoryFilterPrefix),
2240 category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1);
2241 size_t name_length = category.find(';');
2242 if (name_length != std::string::npos && name_length > 0 &&
2243 name_length != category.size() - 1) {
2244 delays_.push_back(DelayValue(category.substr(0, name_length),
2245 category.substr(name_length + 1)));
2246 }
2247 } else if (category.at(0) == '-') {
2248 // Excluded categories start with '-'.
2206 // Remove '-' from category string. 2249 // Remove '-' from category string.
2207 category = category.substr(1); 2250 category = category.substr(1);
2208 excluded_.push_back(category); 2251 excluded_.push_back(category);
2209 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), 2252 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")),
2210 TRACE_DISABLED_BY_DEFAULT("")) == 0) { 2253 TRACE_DISABLED_BY_DEFAULT("")) == 0) {
2211 disabled_.push_back(category); 2254 disabled_.push_back(category);
2212 } else { 2255 } else {
2213 included_.push_back(category); 2256 included_.push_back(category);
2214 } 2257 }
2215 } 2258 }
2216 } 2259 }
2217 2260
2218 void CategoryFilter::WriteString(const StringList& values, 2261 void CategoryFilter::WriteString(const StringList& values,
2219 std::string* out, 2262 std::string* out,
2220 bool included) const { 2263 bool included) const {
2221 bool prepend_comma = !out->empty(); 2264 bool prepend_comma = !out->empty();
2222 int token_cnt = 0; 2265 int token_cnt = 0;
2223 for (StringList::const_iterator ci = values.begin(); 2266 for (StringList::const_iterator ci = values.begin();
2224 ci != values.end(); ++ci) { 2267 ci != values.end(); ++ci) {
2225 if (token_cnt > 0 || prepend_comma) 2268 if (token_cnt > 0 || prepend_comma)
2226 StringAppendF(out, ","); 2269 StringAppendF(out, ",");
2227 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); 2270 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
2228 ++token_cnt; 2271 ++token_cnt;
2229 } 2272 }
2230 } 2273 }
2231 2274
2275 void CategoryFilter::WriteString(const DelayValueList& delays,
2276 std::string* out) const {
2277 bool prepend_comma = !out->empty();
2278 int token_cnt = 0;
2279 for (DelayValueList::const_iterator ci = delays.begin();
2280 ci != delays.end(); ++ci) {
2281 if (token_cnt > 0 || prepend_comma)
2282 StringAppendF(out, ",");
2283 StringAppendF(out, "%s%s;%s)", kSyntheticDelayCategoryFilterPrefix,
2284 ci->first.c_str(), ci->second.c_str());
2285 ++token_cnt;
2286 }
2287 }
2288
2232 std::string CategoryFilter::ToString() const { 2289 std::string CategoryFilter::ToString() const {
2233 std::string filter_string; 2290 std::string filter_string;
2234 WriteString(included_, &filter_string, true); 2291 WriteString(included_, &filter_string, true);
2235 WriteString(disabled_, &filter_string, true); 2292 WriteString(disabled_, &filter_string, true);
2236 WriteString(excluded_, &filter_string, false); 2293 WriteString(excluded_, &filter_string, false);
2294 WriteString(delays_, &filter_string);
2237 return filter_string; 2295 return filter_string;
2238 } 2296 }
2239 2297
2240 bool CategoryFilter::IsCategoryGroupEnabled( 2298 bool CategoryFilter::IsCategoryGroupEnabled(
2241 const char* category_group_name) const { 2299 const char* category_group_name) const {
2242 // TraceLog should call this method only as part of enabling/disabling 2300 // TraceLog should call this method only as part of enabling/disabling
2243 // categories. 2301 // categories.
2244 StringList::const_iterator ci; 2302 StringList::const_iterator ci;
2245 2303
2246 // Check the disabled- filters and the disabled-* wildcard first so that a 2304 // Check the disabled- filters and the disabled-* wildcard first so that a
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 } else { 2340 } else {
2283 included_.clear(); 2341 included_.clear();
2284 } 2342 }
2285 2343
2286 disabled_.insert(disabled_.end(), 2344 disabled_.insert(disabled_.end(),
2287 nested_filter.disabled_.begin(), 2345 nested_filter.disabled_.begin(),
2288 nested_filter.disabled_.end()); 2346 nested_filter.disabled_.end());
2289 excluded_.insert(excluded_.end(), 2347 excluded_.insert(excluded_.end(),
2290 nested_filter.excluded_.begin(), 2348 nested_filter.excluded_.begin(),
2291 nested_filter.excluded_.end()); 2349 nested_filter.excluded_.end());
2350 delays_.insert(delays_.end(),
2351 nested_filter.delays_.begin(),
2352 nested_filter.delays_.end());
2292 } 2353 }
2293 2354
2294 void CategoryFilter::Clear() { 2355 void CategoryFilter::Clear() {
2295 included_.clear(); 2356 included_.clear();
2296 disabled_.clear(); 2357 disabled_.clear();
2297 excluded_.clear(); 2358 excluded_.clear();
2298 } 2359 }
2299 2360
2361 const CategoryFilter::DelayValueList&
2362 CategoryFilter::GetSyntheticDelayValues() const {
2363 return delays_;
2364 }
2365
2300 } // namespace debug 2366 } // namespace debug
2301 } // namespace base 2367 } // namespace base
2302 2368
2303 namespace trace_event_internal { 2369 namespace trace_event_internal {
2304 2370
2305 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( 2371 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
2306 const char* category_group, const char* name) { 2372 const char* category_group, const char* name) {
2307 // The single atom works because for now the category_group can only be "gpu". 2373 // The single atom works because for now the category_group can only be "gpu".
2308 DCHECK(strcmp(category_group, "gpu") == 0); 2374 DCHECK(strcmp(category_group, "gpu") == 0);
2309 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; 2375 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0;
(...skipping 12 matching lines...) Expand all
2322 } 2388 }
2323 2389
2324 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { 2390 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
2325 if (*category_group_enabled_) { 2391 if (*category_group_enabled_) {
2326 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, 2392 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_,
2327 name_, event_handle_); 2393 name_, event_handle_);
2328 } 2394 }
2329 } 2395 }
2330 2396
2331 } // namespace trace_event_internal 2397 } // namespace trace_event_internal
OLDNEW
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_synthetic_delay.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698