Chromium Code Reviews| 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 |