OLD | NEW |
---|---|
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 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1193 event_callback_category_filter_.IsCategoryGroupEnabled(category_group)) | 1194 event_callback_category_filter_.IsCategoryGroupEnabled(category_group)) |
1194 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; | 1195 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; |
1195 g_category_group_enabled[category_index] = enabled_flag; | 1196 g_category_group_enabled[category_index] = enabled_flag; |
1196 } | 1197 } |
1197 | 1198 |
1198 void TraceLog::UpdateCategoryGroupEnabledFlags() { | 1199 void TraceLog::UpdateCategoryGroupEnabledFlags() { |
1199 for (int i = 0; i < g_category_index; i++) | 1200 for (int i = 0; i < g_category_index; i++) |
1200 UpdateCategoryGroupEnabledFlag(i); | 1201 UpdateCategoryGroupEnabledFlag(i); |
1201 } | 1202 } |
1202 | 1203 |
1204 void TraceLog::UpdateSyntheticDelaysFromCategoryFilter() { | |
1205 ResetTraceEventSyntheticDelays(); | |
1206 const CategoryFilter::DelayValueList& delays = | |
1207 category_filter_.GetSyntheticDelayValues(); | |
1208 CategoryFilter::DelayValueList::const_iterator ci; | |
1209 for (ci = delays.begin(); ci != delays.end(); ++ci) { | |
1210 TraceEventSyntheticDelay* delay = | |
1211 TraceEventSyntheticDelay::Lookup(ci->first); | |
1212 StringTokenizer tokens(ci->second, ";"); | |
1213 while (tokens.GetNext()) { | |
1214 double target_duration; | |
1215 if (StringToDouble(tokens.token(), &target_duration)) { | |
1216 delay->SetTargetDuration( | |
1217 TimeDelta::FromMicroseconds(target_duration * 1e6)); | |
1218 } else if (tokens.token() == "static") { | |
1219 delay->SetMode(TraceEventSyntheticDelay::STATIC); | |
1220 } else if (tokens.token() == "oneshot") { | |
1221 delay->SetMode(TraceEventSyntheticDelay::ONE_SHOT); | |
1222 } else if (tokens.token() == "alternating") { | |
1223 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); | |
1224 } | |
1225 } | |
1226 } | |
1227 } | |
1228 | |
1203 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( | 1229 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( |
1204 const char* category_group) { | 1230 const char* category_group) { |
1205 DCHECK(!strchr(category_group, '"')) << | 1231 DCHECK(!strchr(category_group, '"')) << |
1206 "Category groups may not contain double quote"; | 1232 "Category groups may not contain double quote"; |
1207 AutoLock lock(lock_); | 1233 AutoLock lock(lock_); |
1208 | 1234 |
1209 unsigned char* category_group_enabled = NULL; | 1235 unsigned char* category_group_enabled = NULL; |
1210 // Search for pre-existing category group. | 1236 // Search for pre-existing category group. |
1211 for (int i = 0; i < g_category_index; i++) { | 1237 for (int i = 0; i < g_category_index; i++) { |
1212 if (strcmp(g_category_groups[i], category_group) == 0) { | 1238 if (strcmp(g_category_groups[i], category_group) == 0) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1283 if (options != old_options) { | 1309 if (options != old_options) { |
1284 subtle::NoBarrier_Store(&trace_options_, options); | 1310 subtle::NoBarrier_Store(&trace_options_, options); |
1285 logged_events_.reset(CreateTraceBuffer()); | 1311 logged_events_.reset(CreateTraceBuffer()); |
1286 NextGeneration(); | 1312 NextGeneration(); |
1287 } | 1313 } |
1288 | 1314 |
1289 num_traces_recorded_++; | 1315 num_traces_recorded_++; |
1290 | 1316 |
1291 category_filter_ = CategoryFilter(category_filter); | 1317 category_filter_ = CategoryFilter(category_filter); |
1292 UpdateCategoryGroupEnabledFlags(); | 1318 UpdateCategoryGroupEnabledFlags(); |
1319 UpdateSyntheticDelaysFromCategoryFilter(); | |
1293 | 1320 |
1294 if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { | 1321 if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { |
1295 sampling_thread_.reset(new TraceSamplingThread); | 1322 sampling_thread_.reset(new TraceSamplingThread); |
1296 sampling_thread_->RegisterSampleBucket( | 1323 sampling_thread_->RegisterSampleBucket( |
1297 &g_trace_state[0], | 1324 &g_trace_state[0], |
1298 "bucket0", | 1325 "bucket0", |
1299 Bind(&TraceSamplingThread::DefaultSamplingCallback)); | 1326 Bind(&TraceSamplingThread::DefaultSamplingCallback)); |
1300 sampling_thread_->RegisterSampleBucket( | 1327 sampling_thread_->RegisterSampleBucket( |
1301 &g_trace_state[1], | 1328 &g_trace_state[1], |
1302 "bucket1", | 1329 "bucket1", |
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2149 CategoryFilter::CategoryFilter(const std::string& filter_string) { | 2176 CategoryFilter::CategoryFilter(const std::string& filter_string) { |
2150 if (!filter_string.empty()) | 2177 if (!filter_string.empty()) |
2151 Initialize(filter_string); | 2178 Initialize(filter_string); |
2152 else | 2179 else |
2153 Initialize(CategoryFilter::kDefaultCategoryFilterString); | 2180 Initialize(CategoryFilter::kDefaultCategoryFilterString); |
2154 } | 2181 } |
2155 | 2182 |
2156 CategoryFilter::CategoryFilter(const CategoryFilter& cf) | 2183 CategoryFilter::CategoryFilter(const CategoryFilter& cf) |
2157 : included_(cf.included_), | 2184 : included_(cf.included_), |
2158 disabled_(cf.disabled_), | 2185 disabled_(cf.disabled_), |
2159 excluded_(cf.excluded_) { | 2186 excluded_(cf.excluded_), |
2187 delays_(cf.delays_) { | |
2160 } | 2188 } |
2161 | 2189 |
2162 CategoryFilter::~CategoryFilter() { | 2190 CategoryFilter::~CategoryFilter() { |
2163 } | 2191 } |
2164 | 2192 |
2165 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { | 2193 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { |
2166 if (this == &rhs) | 2194 if (this == &rhs) |
2167 return *this; | 2195 return *this; |
2168 | 2196 |
2169 included_ = rhs.included_; | 2197 included_ = rhs.included_; |
2170 disabled_ = rhs.disabled_; | 2198 disabled_ = rhs.disabled_; |
2171 excluded_ = rhs.excluded_; | 2199 excluded_ = rhs.excluded_; |
2200 delays_ = rhs.delays_; | |
2172 return *this; | 2201 return *this; |
2173 } | 2202 } |
2174 | 2203 |
2175 void CategoryFilter::Initialize(const std::string& filter_string) { | 2204 void CategoryFilter::Initialize(const std::string& filter_string) { |
2176 // Tokenize list of categories, delimited by ','. | 2205 // Tokenize list of categories, delimited by ','. |
2177 StringTokenizer tokens(filter_string, ","); | 2206 StringTokenizer tokens(filter_string, ","); |
2178 // Add each token to the appropriate list (included_,excluded_). | 2207 // Add each token to the appropriate list (included_,excluded_). |
2179 while (tokens.GetNext()) { | 2208 while (tokens.GetNext()) { |
2180 std::string category = tokens.token(); | 2209 std::string category = tokens.token(); |
2181 // Ignore empty categories. | 2210 // Ignore empty categories. |
2182 if (category.empty()) | 2211 if (category.empty()) |
2183 continue; | 2212 continue; |
2184 // Excluded categories start with '-'. | 2213 std::vector<std::string> parts; |
2185 if (category.at(0) == '-') { | 2214 SplitString(category, '=', &parts); |
2215 if (parts.size() == 2) { | |
2216 // Synthetic delays are of the form 'delay=options'. | |
2217 delays_.push_back(DelayValue(parts[0], parts[1])); | |
2218 } else if (category.at(0) == '-') { | |
2219 // Excluded categories start with '-'. | |
2186 // Remove '-' from category string. | 2220 // Remove '-' from category string. |
2187 category = category.substr(1); | 2221 category = category.substr(1); |
2188 excluded_.push_back(category); | 2222 excluded_.push_back(category); |
2189 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | 2223 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), |
2190 TRACE_DISABLED_BY_DEFAULT("")) == 0) { | 2224 TRACE_DISABLED_BY_DEFAULT("")) == 0) { |
2191 disabled_.push_back(category); | 2225 disabled_.push_back(category); |
2192 } else { | 2226 } else { |
2193 included_.push_back(category); | 2227 included_.push_back(category); |
2194 } | 2228 } |
2195 } | 2229 } |
2196 } | 2230 } |
2197 | 2231 |
2198 void CategoryFilter::WriteString(const StringList& values, | 2232 void CategoryFilter::WriteString(const StringList& values, |
2199 std::string* out, | 2233 std::string* out, |
2200 bool included) const { | 2234 bool included) const { |
2201 bool prepend_comma = !out->empty(); | 2235 bool prepend_comma = !out->empty(); |
2202 int token_cnt = 0; | 2236 int token_cnt = 0; |
2203 for (StringList::const_iterator ci = values.begin(); | 2237 for (StringList::const_iterator ci = values.begin(); |
2204 ci != values.end(); ++ci) { | 2238 ci != values.end(); ++ci) { |
2205 if (token_cnt > 0 || prepend_comma) | 2239 if (token_cnt > 0 || prepend_comma) |
2206 StringAppendF(out, ","); | 2240 StringAppendF(out, ","); |
2207 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); | 2241 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); |
2208 ++token_cnt; | 2242 ++token_cnt; |
2209 } | 2243 } |
2210 } | 2244 } |
2211 | 2245 |
2246 void CategoryFilter::WriteString(const DelayValueList& delays, | |
2247 std::string* out) const { | |
2248 bool prepend_comma = !out->empty(); | |
2249 int token_cnt = 0; | |
2250 for (DelayValueList::const_iterator ci = delays.begin(); | |
2251 ci != delays.end(); ++ci) { | |
2252 if (token_cnt > 0 || prepend_comma) | |
2253 StringAppendF(out, ","); | |
2254 StringAppendF(out, "%s=%s", ci->first.c_str(), ci->second.c_str()); | |
2255 ++token_cnt; | |
2256 } | |
2257 } | |
2258 | |
2212 std::string CategoryFilter::ToString() const { | 2259 std::string CategoryFilter::ToString() const { |
2213 std::string filter_string; | 2260 std::string filter_string; |
2214 WriteString(included_, &filter_string, true); | 2261 WriteString(included_, &filter_string, true); |
2215 WriteString(disabled_, &filter_string, true); | 2262 WriteString(disabled_, &filter_string, true); |
2216 WriteString(excluded_, &filter_string, false); | 2263 WriteString(excluded_, &filter_string, false); |
2264 WriteString(delays_, &filter_string); | |
2217 return filter_string; | 2265 return filter_string; |
2218 } | 2266 } |
2219 | 2267 |
2220 bool CategoryFilter::IsCategoryGroupEnabled( | 2268 bool CategoryFilter::IsCategoryGroupEnabled( |
2221 const char* category_group_name) const { | 2269 const char* category_group_name) const { |
2222 // TraceLog should call this method only as part of enabling/disabling | 2270 // TraceLog should call this method only as part of enabling/disabling |
2223 // categories. | 2271 // categories. |
2224 StringList::const_iterator ci; | 2272 StringList::const_iterator ci; |
2225 | 2273 |
2226 // Check the disabled- filters and the disabled-* wildcard first so that a | 2274 // Check the disabled- filters and the disabled-* wildcard first so that a |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2262 } else { | 2310 } else { |
2263 included_.clear(); | 2311 included_.clear(); |
2264 } | 2312 } |
2265 | 2313 |
2266 disabled_.insert(disabled_.end(), | 2314 disabled_.insert(disabled_.end(), |
2267 nested_filter.disabled_.begin(), | 2315 nested_filter.disabled_.begin(), |
2268 nested_filter.disabled_.end()); | 2316 nested_filter.disabled_.end()); |
2269 excluded_.insert(excluded_.end(), | 2317 excluded_.insert(excluded_.end(), |
2270 nested_filter.excluded_.begin(), | 2318 nested_filter.excluded_.begin(), |
2271 nested_filter.excluded_.end()); | 2319 nested_filter.excluded_.end()); |
2272 } | 2320 } |
dsinclair1
2014/01/07 19:52:40
Do we need to merge the delay lists as well?
| |
2273 | 2321 |
2274 void CategoryFilter::Clear() { | 2322 void CategoryFilter::Clear() { |
2275 included_.clear(); | 2323 included_.clear(); |
2276 disabled_.clear(); | 2324 disabled_.clear(); |
2277 excluded_.clear(); | 2325 excluded_.clear(); |
2278 } | 2326 } |
2279 | 2327 |
2328 const CategoryFilter::DelayValueList& | |
2329 CategoryFilter::GetSyntheticDelayValues() const { | |
2330 return delays_; | |
2331 } | |
2332 | |
2280 } // namespace debug | 2333 } // namespace debug |
2281 } // namespace base | 2334 } // namespace base |
2282 | 2335 |
2283 namespace trace_event_internal { | 2336 namespace trace_event_internal { |
2284 | 2337 |
2285 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( | 2338 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( |
2286 const char* category_group, const char* name) { | 2339 const char* category_group, const char* name) { |
2287 // The single atom works because for now the category_group can only be "gpu". | 2340 // The single atom works because for now the category_group can only be "gpu". |
2288 DCHECK(strcmp(category_group, "gpu") == 0); | 2341 DCHECK(strcmp(category_group, "gpu") == 0); |
2289 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; | 2342 static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; |
(...skipping 12 matching lines...) Expand all Loading... | |
2302 } | 2355 } |
2303 | 2356 |
2304 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2357 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2305 if (*category_group_enabled_) { | 2358 if (*category_group_enabled_) { |
2306 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2359 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2307 name_, event_handle_); | 2360 name_, event_handle_); |
2308 } | 2361 } |
2309 } | 2362 } |
2310 | 2363 |
2311 } // namespace trace_event_internal | 2364 } // namespace trace_event_internal |
OLD | NEW |