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/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 |