| 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 | 10 |
| 10 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 11 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/values.h" | 13 #include "base/values.h" |
| 13 | 14 |
| 14 namespace trace_analyzer { | 15 namespace trace_analyzer { |
| 15 | 16 |
| 16 // TraceEvent | 17 // TraceEvent |
| 17 | 18 |
| 18 TraceEvent::TraceEvent() | 19 TraceEvent::TraceEvent() |
| (...skipping 18 matching lines...) Expand all Loading... |
| 37 base::DictionaryValue* args = NULL; | 38 base::DictionaryValue* args = NULL; |
| 38 | 39 |
| 39 if (!dictionary->GetString("ph", &phase_str)) { | 40 if (!dictionary->GetString("ph", &phase_str)) { |
| 40 LOG(ERROR) << "ph is missing from TraceEvent JSON"; | 41 LOG(ERROR) << "ph is missing from TraceEvent JSON"; |
| 41 return false; | 42 return false; |
| 42 } | 43 } |
| 43 | 44 |
| 44 phase = *phase_str.data(); | 45 phase = *phase_str.data(); |
| 45 | 46 |
| 46 bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA); | 47 bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA); |
| 47 bool require_id = (phase == TRACE_EVENT_PHASE_START || | 48 bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN || |
| 48 phase == TRACE_EVENT_PHASE_FINISH); | 49 phase == TRACE_EVENT_PHASE_ASYNC_STEP || |
| 50 phase == TRACE_EVENT_PHASE_ASYNC_END); |
| 49 | 51 |
| 50 if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) { | 52 if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) { |
| 51 LOG(ERROR) << "pid is missing from TraceEvent JSON"; | 53 LOG(ERROR) << "pid is missing from TraceEvent JSON"; |
| 52 return false; | 54 return false; |
| 53 } | 55 } |
| 54 if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) { | 56 if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) { |
| 55 LOG(ERROR) << "tid is missing from TraceEvent JSON"; | 57 LOG(ERROR) << "tid is missing from TraceEvent JSON"; |
| 56 return false; | 58 return false; |
| 57 } | 59 } |
| 58 if (require_origin && !dictionary->GetDouble("ts", ×tamp)) { | 60 if (require_origin && !dictionary->GetDouble("ts", ×tamp)) { |
| 59 LOG(ERROR) << "ts is missing from TraceEvent JSON"; | 61 LOG(ERROR) << "ts is missing from TraceEvent JSON"; |
| 60 return false; | 62 return false; |
| 61 } | 63 } |
| 62 if (!dictionary->GetString("cat", &category)) { | 64 if (!dictionary->GetString("cat", &category)) { |
| 63 LOG(ERROR) << "cat is missing from TraceEvent JSON"; | 65 LOG(ERROR) << "cat is missing from TraceEvent JSON"; |
| 64 return false; | 66 return false; |
| 65 } | 67 } |
| 66 if (!dictionary->GetString("name", &name)) { | 68 if (!dictionary->GetString("name", &name)) { |
| 67 LOG(ERROR) << "name is missing from TraceEvent JSON"; | 69 LOG(ERROR) << "name is missing from TraceEvent JSON"; |
| 68 return false; | 70 return false; |
| 69 } | 71 } |
| 70 if (!dictionary->GetDictionary("args", &args)) { | 72 if (!dictionary->GetDictionary("args", &args)) { |
| 71 LOG(ERROR) << "args is missing from TraceEvent JSON"; | 73 LOG(ERROR) << "args is missing from TraceEvent JSON"; |
| 72 return false; | 74 return false; |
| 73 } | 75 } |
| 74 if (require_id && !dictionary->GetString("id", &id)) { | 76 if (require_id && !dictionary->GetString("id", &id)) { |
| 75 LOG(ERROR) << "id is missing from START/FINISH TraceEvent JSON"; | 77 LOG(ERROR) << "id is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON"; |
| 76 return false; | 78 return false; |
| 77 } | 79 } |
| 78 | 80 |
| 79 // For each argument, copy the type and create a trace_analyzer::TraceValue. | 81 // For each argument, copy the type and create a trace_analyzer::TraceValue. |
| 80 base::DictionaryValue::key_iterator keyi = args->begin_keys(); | 82 base::DictionaryValue::key_iterator keyi = args->begin_keys(); |
| 81 for (; keyi != args->end_keys(); ++keyi) { | 83 for (; keyi != args->end_keys(); ++keyi) { |
| 82 std::string str; | 84 std::string str; |
| 83 bool boolean = false; | 85 bool boolean = false; |
| 84 int int_num = 0; | 86 int int_num = 0; |
| 85 double double_num = 0.0; | 87 double double_num = 0.0; |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 Query begin(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_BEGIN)); | 697 Query begin(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_BEGIN)); |
| 696 Query end(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_END)); | 698 Query end(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_END)); |
| 697 Query match(Query::EventName() == Query::OtherName() && | 699 Query match(Query::EventName() == Query::OtherName() && |
| 698 Query::EventCategory() == Query::OtherCategory() && | 700 Query::EventCategory() == Query::OtherCategory() && |
| 699 Query::EventTid() == Query::OtherTid() && | 701 Query::EventTid() == Query::OtherTid() && |
| 700 Query::EventPid() == Query::OtherPid()); | 702 Query::EventPid() == Query::OtherPid()); |
| 701 | 703 |
| 702 AssociateEvents(begin, end, match); | 704 AssociateEvents(begin, end, match); |
| 703 } | 705 } |
| 704 | 706 |
| 705 void TraceAnalyzer::AssociateStartFinishEvents() { | 707 void TraceAnalyzer::AssociateAsyncBeginEndEvents() { |
| 706 using trace_analyzer::Query; | 708 using trace_analyzer::Query; |
| 707 | 709 |
| 708 Query begin(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_START)); | 710 Query begin( |
| 709 Query end(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_FINISH)); | 711 Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_ASYNC_BEGIN) || |
| 712 Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_ASYNC_STEP)); |
| 713 Query end(Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_ASYNC_END) || |
| 714 Query::EventPhase() == Query::Phase(TRACE_EVENT_PHASE_ASYNC_STEP)); |
| 710 Query match(Query::EventName() == Query::OtherName() && | 715 Query match(Query::EventName() == Query::OtherName() && |
| 711 Query::EventCategory() == Query::OtherCategory() && | 716 Query::EventCategory() == Query::OtherCategory() && |
| 712 Query::EventId() == Query::OtherId()); | 717 Query::EventId() == Query::OtherId()); |
| 713 | 718 |
| 714 AssociateEvents(begin, end, match); | 719 AssociateEvents(begin, end, match); |
| 715 } | 720 } |
| 716 | 721 |
| 717 void TraceAnalyzer::AssociateEvents(const Query& first, | 722 void TraceAnalyzer::AssociateEvents(const Query& first, |
| 718 const Query& second, | 723 const Query& second, |
| 719 const Query& match) { | 724 const Query& match) { |
| 720 DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after " | 725 DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after " |
| 721 "FindEvents"; | 726 "FindEvents"; |
| 722 | 727 |
| 723 // Search for matching begin/end event pairs. When a matching end is found, | 728 // Search for matching begin/end event pairs. When a matching end is found, |
| 724 // it is associated with the begin event. | 729 // it is associated with the begin event. |
| 725 std::vector<TraceEvent*> begin_stack; | 730 std::vector<TraceEvent*> begin_stack; |
| 726 for (size_t event_index = 0; event_index < raw_events_.size(); | 731 for (size_t event_index = 0; event_index < raw_events_.size(); |
| 727 ++event_index) { | 732 ++event_index) { |
| 728 | 733 |
| 729 TraceEvent& this_event = raw_events_[event_index]; | 734 TraceEvent& this_event = raw_events_[event_index]; |
| 730 | 735 |
| 731 if (first.Evaluate(this_event)) { | 736 if (second.Evaluate(this_event)) { |
| 732 begin_stack.push_back(&this_event); | |
| 733 } else if (second.Evaluate(this_event)) { | |
| 734 // Search stack for matching begin, starting from end. | 737 // Search stack for matching begin, starting from end. |
| 735 for (int stack_index = static_cast<int>(begin_stack.size()) - 1; | 738 for (int stack_index = static_cast<int>(begin_stack.size()) - 1; |
| 736 stack_index >= 0; --stack_index) { | 739 stack_index >= 0; --stack_index) { |
| 737 TraceEvent& begin_event = *begin_stack[stack_index]; | 740 TraceEvent& begin_event = *begin_stack[stack_index]; |
| 738 | 741 |
| 739 // Temporarily set other to test against the match query. | 742 // Temporarily set other to test against the match query. |
| 740 const TraceEvent* other_backup = begin_event.other_event; | 743 const TraceEvent* other_backup = begin_event.other_event; |
| 741 begin_event.other_event = &this_event; | 744 begin_event.other_event = &this_event; |
| 742 if (match.Evaluate(begin_event)) { | 745 if (match.Evaluate(begin_event)) { |
| 743 // Found a matching begin/end pair. | 746 // Found a matching begin/end pair. |
| 744 // Set event association: | |
| 745 this_event.other_event = &begin_event; | |
| 746 // Erase the matching begin event index from the stack. | 747 // Erase the matching begin event index from the stack. |
| 747 begin_stack.erase(begin_stack.begin() + stack_index); | 748 begin_stack.erase(begin_stack.begin() + stack_index); |
| 748 break; | 749 break; |
| 749 } | 750 } |
| 750 | 751 |
| 751 // Not a match, restore original other and continue. | 752 // Not a match, restore original other and continue. |
| 752 begin_event.other_event = other_backup; | 753 begin_event.other_event = other_backup; |
| 753 } | 754 } |
| 754 } | 755 } |
| 756 // Even if this_event is a |second| event that has matched an earlier |
| 757 // |first| event, it can still also be a |first| event and be associated |
| 758 // with a later |second| event. |
| 759 if (first.Evaluate(this_event)) { |
| 760 begin_stack.push_back(&this_event); |
| 761 } |
| 755 } | 762 } |
| 756 } | 763 } |
| 757 | 764 |
| 758 void TraceAnalyzer::MergeAssociatedEventArgs() { | 765 void TraceAnalyzer::MergeAssociatedEventArgs() { |
| 759 for (size_t i = 0; i < raw_events_.size(); ++i) { | 766 for (size_t i = 0; i < raw_events_.size(); ++i) { |
| 760 if (raw_events_[i].other_event) { | 767 // Merge all associated events with the first event. |
| 768 const TraceEvent* other = raw_events_[i].other_event; |
| 769 // Avoid looping by keeping set of encountered TraceEvents. |
| 770 std::set<const TraceEvent*> encounters; |
| 771 encounters.insert(&raw_events_[i]); |
| 772 while (other && encounters.find(other) == encounters.end()) { |
| 773 encounters.insert(other); |
| 761 raw_events_[i].arg_numbers.insert( | 774 raw_events_[i].arg_numbers.insert( |
| 762 raw_events_[i].other_event->arg_numbers.begin(), | 775 other->arg_numbers.begin(), |
| 763 raw_events_[i].other_event->arg_numbers.end()); | 776 other->arg_numbers.end()); |
| 764 raw_events_[i].arg_strings.insert( | 777 raw_events_[i].arg_strings.insert( |
| 765 raw_events_[i].other_event->arg_strings.begin(), | 778 other->arg_strings.begin(), |
| 766 raw_events_[i].other_event->arg_strings.end()); | 779 other->arg_strings.end()); |
| 780 other = other->other_event; |
| 767 } | 781 } |
| 768 } | 782 } |
| 769 } | 783 } |
| 770 | 784 |
| 771 size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) { | 785 size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) { |
| 772 allow_assocation_changes_ = false; | 786 allow_assocation_changes_ = false; |
| 773 output->clear(); | 787 output->clear(); |
| 774 return FindMatchingEvents(raw_events_, query, output); | 788 return FindMatchingEvents(raw_events_, query, output); |
| 775 } | 789 } |
| 776 | 790 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 size_t count = 0u; | 934 size_t count = 0u; |
| 921 for (size_t i = begin_position; i < end_position; ++i) { | 935 for (size_t i = begin_position; i < end_position; ++i) { |
| 922 if (query.Evaluate(*events.at(i))) | 936 if (query.Evaluate(*events.at(i))) |
| 923 ++count; | 937 ++count; |
| 924 } | 938 } |
| 925 return count; | 939 return count; |
| 926 } | 940 } |
| 927 | 941 |
| 928 } // namespace trace_analyzer | 942 } // namespace trace_analyzer |
| 929 | 943 |
| OLD | NEW |