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/test/trace_event_analyzer.h" | 5 #include "base/test/trace_event_analyzer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <math.h> | 8 #include <math.h> |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 return false; | 84 return false; |
85 } | 85 } |
86 | 86 |
87 // For each argument, copy the type and create a trace_analyzer::TraceValue. | 87 // For each argument, copy the type and create a trace_analyzer::TraceValue. |
88 for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd(); | 88 for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd(); |
89 it.Advance()) { | 89 it.Advance()) { |
90 std::string str; | 90 std::string str; |
91 bool boolean = false; | 91 bool boolean = false; |
92 int int_num = 0; | 92 int int_num = 0; |
93 double double_num = 0.0; | 93 double double_num = 0.0; |
94 if (it.value().GetAsString(&str)) | 94 if (it.value().GetAsString(&str)) { |
95 arg_strings[it.key()] = str; | 95 arg_strings[it.key()] = str; |
96 else if (it.value().GetAsInteger(&int_num)) | 96 } else if (it.value().GetAsInteger(&int_num)) { |
97 arg_numbers[it.key()] = static_cast<double>(int_num); | 97 arg_numbers[it.key()] = static_cast<double>(int_num); |
98 else if (it.value().GetAsBoolean(&boolean)) | 98 } else if (it.value().GetAsBoolean(&boolean)) { |
99 arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0); | 99 arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0); |
100 else if (it.value().GetAsDouble(&double_num)) | 100 } else if (it.value().GetAsDouble(&double_num)) { |
101 arg_numbers[it.key()] = double_num; | 101 arg_numbers[it.key()] = double_num; |
102 else { | 102 } else { |
103 LOG(WARNING) << "Value type of argument is not supported: " << | 103 LOG(WARNING) << "Value type of argument is not supported: " << |
104 static_cast<int>(it.value().GetType()); | 104 static_cast<int>(it.value().GetType()); |
105 continue; // Skip non-supported arguments. | 105 continue; // Skip non-supported arguments. |
106 } | 106 } |
107 } | 107 } |
108 | 108 |
109 return true; | 109 return true; |
110 } | 110 } |
111 | 111 |
112 double TraceEvent::GetAbsTimeToOtherEvent() const { | 112 double TraceEvent::GetAbsTimeToOtherEvent() const { |
(...skipping 23 matching lines...) Expand all Loading... | |
136 bool TraceEvent::HasStringArg(const std::string& name) const { | 136 bool TraceEvent::HasStringArg(const std::string& name) const { |
137 return (arg_strings.find(name) != arg_strings.end()); | 137 return (arg_strings.find(name) != arg_strings.end()); |
138 } | 138 } |
139 | 139 |
140 bool TraceEvent::HasNumberArg(const std::string& name) const { | 140 bool TraceEvent::HasNumberArg(const std::string& name) const { |
141 return (arg_numbers.find(name) != arg_numbers.end()); | 141 return (arg_numbers.find(name) != arg_numbers.end()); |
142 } | 142 } |
143 | 143 |
144 std::string TraceEvent::GetKnownArgAsString(const std::string& name) const { | 144 std::string TraceEvent::GetKnownArgAsString(const std::string& name) const { |
145 std::string arg_string; | 145 std::string arg_string; |
146 if (GetArgAsString(name, &arg_string)) | 146 bool result = GetArgAsString(name, &arg_string); |
Nico
2014/03/19 10:29:21
Not sure I love this change, as GetArgAsString doe
Peter Kasting
2014/03/19 21:14:16
True. But the DCHECKs here say it can never retur
| |
147 return arg_string; | 147 DCHECK(result); |
148 NOTREACHED(); | 148 return arg_string; |
149 return std::string(); | |
150 } | 149 } |
151 | 150 |
152 double TraceEvent::GetKnownArgAsDouble(const std::string& name) const { | 151 double TraceEvent::GetKnownArgAsDouble(const std::string& name) const { |
153 double arg_double; | 152 double arg_double; |
154 if (GetArgAsNumber(name, &arg_double)) | 153 bool result = GetArgAsNumber(name, &arg_double); |
155 return arg_double; | 154 DCHECK(result); |
156 NOTREACHED(); | 155 return arg_double; |
157 return 0; | |
158 } | 156 } |
159 | 157 |
160 int TraceEvent::GetKnownArgAsInt(const std::string& name) const { | 158 int TraceEvent::GetKnownArgAsInt(const std::string& name) const { |
161 double arg_double; | 159 double arg_double; |
162 if (GetArgAsNumber(name, &arg_double)) | 160 bool result = GetArgAsNumber(name, &arg_double); |
163 return static_cast<int>(arg_double); | 161 DCHECK(result); |
164 NOTREACHED(); | 162 return static_cast<int>(arg_double); |
165 return 0; | |
166 } | 163 } |
167 | 164 |
168 bool TraceEvent::GetKnownArgAsBool(const std::string& name) const { | 165 bool TraceEvent::GetKnownArgAsBool(const std::string& name) const { |
169 double arg_double; | 166 double arg_double; |
170 if (GetArgAsNumber(name, &arg_double)) | 167 bool result = GetArgAsNumber(name, &arg_double); |
171 return (arg_double != 0.0); | 168 DCHECK(result); |
172 NOTREACHED(); | 169 return (arg_double != 0.0); |
173 return false; | |
174 } | 170 } |
175 | 171 |
176 // QueryNode | 172 // QueryNode |
177 | 173 |
178 QueryNode::QueryNode(const Query& query) : query_(query) { | 174 QueryNode::QueryNode(const Query& query) : query_(query) { |
179 } | 175 } |
180 | 176 |
181 QueryNode::~QueryNode() { | 177 QueryNode::~QueryNode() { |
182 } | 178 } |
183 | 179 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 bool is_bool = GetAsDouble(event, &bool_value); | 248 bool is_bool = GetAsDouble(event, &bool_value); |
253 if (is_bool) | 249 if (is_bool) |
254 return (bool_value != 0.0); | 250 return (bool_value != 0.0); |
255 | 251 |
256 // string is true if it is non-empty: | 252 // string is true if it is non-empty: |
257 std::string str_value; | 253 std::string str_value; |
258 bool is_str = GetAsString(event, &str_value); | 254 bool is_str = GetAsString(event, &str_value); |
259 if (is_str) | 255 if (is_str) |
260 return !str_value.empty(); | 256 return !str_value.empty(); |
261 | 257 |
262 DCHECK(type_ == QUERY_BOOLEAN_OPERATOR) | 258 DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_) |
263 << "Invalid query: missing boolean expression"; | 259 << "Invalid query: missing boolean expression"; |
264 DCHECK(left_.get() && (right_.get() || is_unary_operator())); | 260 DCHECK(left_.get()); |
261 DCHECK(right_.get() || is_unary_operator()); | |
265 | 262 |
266 if (is_comparison_operator()) { | 263 if (is_comparison_operator()) { |
267 DCHECK(left().is_value() && right().is_value()) | 264 DCHECK(left().is_value() && right().is_value()) |
268 << "Invalid query: comparison operator used between event member and " | 265 << "Invalid query: comparison operator used between event member and " |
269 "value."; | 266 "value."; |
270 bool compare_result = false; | 267 bool compare_result = false; |
271 if (CompareAsDouble(event, &compare_result)) | 268 if (CompareAsDouble(event, &compare_result)) |
272 return compare_result; | 269 return compare_result; |
273 else if (CompareAsString(event, &compare_result)) | 270 if (CompareAsString(event, &compare_result)) |
274 return compare_result; | 271 return compare_result; |
275 return false; | 272 return false; |
276 } | 273 } |
277 // It's a logical operator. | 274 // It's a logical operator. |
278 switch (operator_) { | 275 switch (operator_) { |
279 case OP_AND: | 276 case OP_AND: |
280 return left().Evaluate(event) && right().Evaluate(event); | 277 return left().Evaluate(event) && right().Evaluate(event); |
281 case OP_OR: | 278 case OP_OR: |
282 return left().Evaluate(event) || right().Evaluate(event); | 279 return left().Evaluate(event) || right().Evaluate(event); |
283 case OP_NOT: | 280 case OP_NOT: |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 return true; | 352 return true; |
356 default: | 353 default: |
357 NOTREACHED(); | 354 NOTREACHED(); |
358 return false; | 355 return false; |
359 } | 356 } |
360 return true; | 357 return true; |
361 } | 358 } |
362 | 359 |
363 bool Query::EvaluateArithmeticOperator(const TraceEvent& event, | 360 bool Query::EvaluateArithmeticOperator(const TraceEvent& event, |
364 double* num) const { | 361 double* num) const { |
365 DCHECK(type_ == QUERY_ARITHMETIC_OPERATOR); | 362 DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_); |
366 DCHECK(left_.get() && (right_.get() || is_unary_operator())); | 363 DCHECK(left_.get()); |
364 DCHECK(right_.get() || is_unary_operator()); | |
367 | 365 |
368 double lhs = 0, rhs = 0; | 366 double lhs = 0, rhs = 0; |
369 if (!left().GetAsDouble(event, &lhs)) | 367 if (!left().GetAsDouble(event, &lhs)) |
370 return false; | 368 return false; |
371 if (!is_unary_operator() && !right().GetAsDouble(event, &rhs)) | 369 if (!is_unary_operator() && !right().GetAsDouble(event, &rhs)) |
372 return false; | 370 return false; |
373 | 371 |
374 switch (operator_) { | 372 switch (operator_) { |
375 case OP_ADD: | 373 case OP_ADD: |
376 *num = lhs + rhs; | 374 *num = lhs + rhs; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 case QUERY_STRING: | 416 case QUERY_STRING: |
419 *str = string_; | 417 *str = string_; |
420 return true; | 418 return true; |
421 default: | 419 default: |
422 return false; | 420 return false; |
423 } | 421 } |
424 } | 422 } |
425 | 423 |
426 bool Query::GetMemberValueAsDouble(const TraceEvent& event, | 424 bool Query::GetMemberValueAsDouble(const TraceEvent& event, |
427 double* num) const { | 425 double* num) const { |
428 DCHECK(type_ == QUERY_EVENT_MEMBER); | 426 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); |
429 | 427 |
430 // This could be a request for a member of |event| or a member of |event|'s | 428 // This could be a request for a member of |event| or a member of |event|'s |
431 // associated event. Store the target event in the_event: | 429 // associated event. Store the target event in the_event: |
432 const TraceEvent* the_event = (member_ < OTHER_PID) ? | 430 const TraceEvent* the_event = (member_ < OTHER_PID) ? |
433 &event : event.other_event; | 431 &event : event.other_event; |
434 | 432 |
435 // Request for member of associated event, but there is no associated event. | 433 // Request for member of associated event, but there is no associated event. |
436 if (!the_event) | 434 if (!the_event) |
437 return false; | 435 return false; |
438 | 436 |
439 switch (member_) { | 437 switch (member_) { |
440 case EVENT_PID: | 438 case EVENT_PID: |
441 case OTHER_PID: | 439 case OTHER_PID: |
442 *num = static_cast<double>(the_event->thread.process_id); | 440 *num = static_cast<double>(the_event->thread.process_id); |
443 return true; | 441 return true; |
444 case EVENT_TID: | 442 case EVENT_TID: |
445 case OTHER_TID: | 443 case OTHER_TID: |
446 *num = static_cast<double>(the_event->thread.thread_id); | 444 *num = static_cast<double>(the_event->thread.thread_id); |
447 return true; | 445 return true; |
448 case EVENT_TIME: | 446 case EVENT_TIME: |
449 case OTHER_TIME: | 447 case OTHER_TIME: |
450 *num = the_event->timestamp; | 448 *num = the_event->timestamp; |
451 return true; | 449 return true; |
452 case EVENT_DURATION: | 450 case EVENT_DURATION: |
453 if (the_event->has_other_event()) { | 451 if (!the_event->has_other_event()) |
454 *num = the_event->GetAbsTimeToOtherEvent(); | 452 return false; |
455 return true; | 453 *num = the_event->GetAbsTimeToOtherEvent(); |
456 } | 454 return true; |
457 return false; | |
458 case EVENT_COMPLETE_DURATION: | 455 case EVENT_COMPLETE_DURATION: |
459 if (the_event->phase == TRACE_EVENT_PHASE_COMPLETE) { | 456 if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE) |
460 *num = the_event->duration; | 457 return false; |
461 return true; | 458 *num = the_event->duration; |
462 } | 459 return true; |
463 return false; | |
464 case EVENT_PHASE: | 460 case EVENT_PHASE: |
465 case OTHER_PHASE: | 461 case OTHER_PHASE: |
466 *num = static_cast<double>(the_event->phase); | 462 *num = static_cast<double>(the_event->phase); |
467 return true; | 463 return true; |
468 case EVENT_HAS_STRING_ARG: | 464 case EVENT_HAS_STRING_ARG: |
469 case OTHER_HAS_STRING_ARG: | 465 case OTHER_HAS_STRING_ARG: |
470 *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0); | 466 *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0); |
471 return true; | 467 return true; |
472 case EVENT_HAS_NUMBER_ARG: | 468 case EVENT_HAS_NUMBER_ARG: |
473 case OTHER_HAS_NUMBER_ARG: | 469 case OTHER_HAS_NUMBER_ARG: |
(...skipping 13 matching lines...) Expand all Loading... | |
487 // return 1.0 (true) if the other event exists | 483 // return 1.0 (true) if the other event exists |
488 *num = event.other_event ? 1.0 : 0.0; | 484 *num = event.other_event ? 1.0 : 0.0; |
489 return true; | 485 return true; |
490 default: | 486 default: |
491 return false; | 487 return false; |
492 } | 488 } |
493 } | 489 } |
494 | 490 |
495 bool Query::GetMemberValueAsString(const TraceEvent& event, | 491 bool Query::GetMemberValueAsString(const TraceEvent& event, |
496 std::string* str) const { | 492 std::string* str) const { |
497 DCHECK(type_ == QUERY_EVENT_MEMBER); | 493 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); |
498 | 494 |
499 // This could be a request for a member of |event| or a member of |event|'s | 495 // This could be a request for a member of |event| or a member of |event|'s |
500 // associated event. Store the target event in the_event: | 496 // associated event. Store the target event in the_event: |
501 const TraceEvent* the_event = (member_ < OTHER_PID) ? | 497 const TraceEvent* the_event = (member_ < OTHER_PID) ? |
502 &event : event.other_event; | 498 &event : event.other_event; |
503 | 499 |
504 // Request for member of associated event, but there is no associated event. | 500 // Request for member of associated event, but there is no associated event. |
505 if (!the_event) | 501 if (!the_event) |
506 return false; | 502 return false; |
507 | 503 |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 Query match(Query::EventName() == Query::OtherName() && | 722 Query match(Query::EventName() == Query::OtherName() && |
727 Query::EventCategory() == Query::OtherCategory() && | 723 Query::EventCategory() == Query::OtherCategory() && |
728 Query::EventId() == Query::OtherId()); | 724 Query::EventId() == Query::OtherId()); |
729 | 725 |
730 AssociateEvents(begin, end, match); | 726 AssociateEvents(begin, end, match); |
731 } | 727 } |
732 | 728 |
733 void TraceAnalyzer::AssociateEvents(const Query& first, | 729 void TraceAnalyzer::AssociateEvents(const Query& first, |
734 const Query& second, | 730 const Query& second, |
735 const Query& match) { | 731 const Query& match) { |
736 DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after " | 732 DCHECK(allow_assocation_changes_) |
737 "FindEvents"; | 733 << "AssociateEvents not allowed after FindEvents"; |
738 | 734 |
739 // Search for matching begin/end event pairs. When a matching end is found, | 735 // Search for matching begin/end event pairs. When a matching end is found, |
740 // it is associated with the begin event. | 736 // it is associated with the begin event. |
741 std::vector<TraceEvent*> begin_stack; | 737 std::vector<TraceEvent*> begin_stack; |
742 for (size_t event_index = 0; event_index < raw_events_.size(); | 738 for (size_t event_index = 0; event_index < raw_events_.size(); |
743 ++event_index) { | 739 ++event_index) { |
744 | 740 |
745 TraceEvent& this_event = raw_events_[event_index]; | 741 TraceEvent& this_event = raw_events_[event_index]; |
746 | 742 |
747 if (second.Evaluate(this_event)) { | 743 if (second.Evaluate(this_event)) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
831 if (string_it != this_event.arg_strings.end()) | 827 if (string_it != this_event.arg_strings.end()) |
832 thread_names_[this_event.thread] = string_it->second; | 828 thread_names_[this_event.thread] = string_it->second; |
833 } | 829 } |
834 } | 830 } |
835 | 831 |
836 // TraceEventVector utility functions. | 832 // TraceEventVector utility functions. |
837 | 833 |
838 bool GetRateStats(const TraceEventVector& events, | 834 bool GetRateStats(const TraceEventVector& events, |
839 RateStats* stats, | 835 RateStats* stats, |
840 const RateStatsOptions* options) { | 836 const RateStatsOptions* options) { |
841 CHECK(stats); | 837 DCHECK(stats); |
842 // Need at least 3 events to calculate rate stats. | 838 // Need at least 3 events to calculate rate stats. |
843 const size_t kMinEvents = 3; | 839 const size_t kMinEvents = 3; |
844 if (events.size() < kMinEvents) { | 840 if (events.size() < kMinEvents) { |
845 LOG(ERROR) << "Not enough events: " << events.size(); | 841 LOG(ERROR) << "Not enough events: " << events.size(); |
846 return false; | 842 return false; |
847 } | 843 } |
848 | 844 |
849 std::vector<double> deltas; | 845 std::vector<double> deltas; |
850 size_t num_deltas = events.size() - 1; | 846 size_t num_deltas = events.size() - 1; |
851 for (size_t i = 0; i < num_deltas; ++i) { | 847 for (size_t i = 0; i < num_deltas; ++i) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
885 stats->standard_deviation_us = | 881 stats->standard_deviation_us = |
886 sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1)); | 882 sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1)); |
887 | 883 |
888 return true; | 884 return true; |
889 } | 885 } |
890 | 886 |
891 bool FindFirstOf(const TraceEventVector& events, | 887 bool FindFirstOf(const TraceEventVector& events, |
892 const Query& query, | 888 const Query& query, |
893 size_t position, | 889 size_t position, |
894 size_t* return_index) { | 890 size_t* return_index) { |
895 CHECK(return_index); | 891 DCHECK(return_index); |
896 for (size_t i = position; i < events.size(); ++i) { | 892 for (size_t i = position; i < events.size(); ++i) { |
897 if (query.Evaluate(*events.at(i))) { | 893 if (query.Evaluate(*events[i])) { |
898 *return_index = i; | 894 *return_index = i; |
899 return true; | 895 return true; |
900 } | 896 } |
901 } | 897 } |
902 return false; | 898 return false; |
903 } | 899 } |
904 | 900 |
905 bool FindLastOf(const TraceEventVector& events, | 901 bool FindLastOf(const TraceEventVector& events, |
906 const Query& query, | 902 const Query& query, |
907 size_t position, | 903 size_t position, |
908 size_t* return_index) { | 904 size_t* return_index) { |
909 CHECK(return_index); | 905 DCHECK(return_index); |
910 if (events.empty()) | 906 if (events.empty()) |
911 return false; | 907 return false; |
912 position = (position < events.size()) ? position : events.size() - 1; | 908 position = (position < events.size()) ? position : events.size() - 1; |
913 for (;;) { | 909 for (;;) { |
914 if (query.Evaluate(*events.at(position))) { | 910 if (query.Evaluate(*events[position])) { |
915 *return_index = position; | 911 *return_index = position; |
916 return true; | 912 return true; |
917 } | 913 } |
918 if (position == 0) | 914 if (position == 0) |
919 return false; | 915 return false; |
920 --position; | 916 --position; |
921 } | 917 } |
922 return false; | 918 return false; |
923 } | 919 } |
924 | 920 |
925 bool FindClosest(const TraceEventVector& events, | 921 bool FindClosest(const TraceEventVector& events, |
926 const Query& query, | 922 const Query& query, |
927 size_t position, | 923 size_t position, |
928 size_t* return_closest, | 924 size_t* return_closest, |
929 size_t* return_second_closest) { | 925 size_t* return_second_closest) { |
930 CHECK(return_closest); | 926 DCHECK(return_closest); |
931 if (events.empty() || position >= events.size()) | 927 if (events.empty() || position >= events.size()) |
932 return false; | 928 return false; |
933 size_t closest = events.size(); | 929 size_t closest = events.size(); |
934 size_t second_closest = events.size(); | 930 size_t second_closest = events.size(); |
935 for (size_t i = 0; i < events.size(); ++i) { | 931 for (size_t i = 0; i < events.size(); ++i) { |
936 if (!query.Evaluate(*events.at(i))) | 932 if (!query.Evaluate(*events.at(i))) |
937 continue; | 933 continue; |
938 if (closest == events.size()) { | 934 if (closest == events.size()) { |
939 closest = i; | 935 closest = i; |
940 continue; | 936 continue; |
(...skipping 27 matching lines...) Expand all Loading... | |
968 end_position = (end_position < events.size()) ? end_position : events.size(); | 964 end_position = (end_position < events.size()) ? end_position : events.size(); |
969 size_t count = 0u; | 965 size_t count = 0u; |
970 for (size_t i = begin_position; i < end_position; ++i) { | 966 for (size_t i = begin_position; i < end_position; ++i) { |
971 if (query.Evaluate(*events.at(i))) | 967 if (query.Evaluate(*events.at(i))) |
972 ++count; | 968 ++count; |
973 } | 969 } |
974 return count; | 970 return count; |
975 } | 971 } |
976 | 972 |
977 } // namespace trace_analyzer | 973 } // namespace trace_analyzer |
OLD | NEW |