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 <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 case QUERY_EVENT_MEMBER: | 442 case QUERY_EVENT_MEMBER: |
443 return GetMemberValueAsString(event, str); | 443 return GetMemberValueAsString(event, str); |
444 case QUERY_STRING: | 444 case QUERY_STRING: |
445 *str = string_; | 445 *str = string_; |
446 return true; | 446 return true; |
447 default: | 447 default: |
448 return false; | 448 return false; |
449 } | 449 } |
450 } | 450 } |
451 | 451 |
| 452 const TraceEvent* Query::SelectTargetEvent(const TraceEvent* event, |
| 453 TraceEventMember member) { |
| 454 if (member >= OTHER_FIRST_MEMBER && member <= OTHER_LAST_MEMBER) { |
| 455 return event->other_event; |
| 456 } else if (member >= PREV_FIRST_MEMBER && member <= PREV_LAST_MEMBER) { |
| 457 return event->prev_event; |
| 458 } else { |
| 459 return event; |
| 460 } |
| 461 } |
| 462 |
452 bool Query::GetMemberValueAsDouble(const TraceEvent& event, | 463 bool Query::GetMemberValueAsDouble(const TraceEvent& event, |
453 double* num) const { | 464 double* num) const { |
454 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); | 465 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); |
455 | 466 |
456 // This could be a request for a member of |event| or a member of |event|'s | 467 // This could be a request for a member of |event| or a member of |event|'s |
457 // associated event. Store the target event in the_event: | 468 // associated previous or next event. Store the target event in the_event: |
458 const TraceEvent* the_event = (member_ < OTHER_PID) ? | 469 const TraceEvent* the_event = SelectTargetEvent(&event, member_); |
459 &event : event.other_event; | |
460 | 470 |
461 // Request for member of associated event, but there is no associated event. | 471 // Request for member of associated event, but there is no associated event. |
462 if (!the_event) | 472 if (!the_event) |
463 return false; | 473 return false; |
464 | 474 |
465 switch (member_) { | 475 switch (member_) { |
466 case EVENT_PID: | 476 case EVENT_PID: |
467 case OTHER_PID: | 477 case OTHER_PID: |
| 478 case PREV_PID: |
468 *num = static_cast<double>(the_event->thread.process_id); | 479 *num = static_cast<double>(the_event->thread.process_id); |
469 return true; | 480 return true; |
470 case EVENT_TID: | 481 case EVENT_TID: |
471 case OTHER_TID: | 482 case OTHER_TID: |
| 483 case PREV_TID: |
472 *num = static_cast<double>(the_event->thread.thread_id); | 484 *num = static_cast<double>(the_event->thread.thread_id); |
473 return true; | 485 return true; |
474 case EVENT_TIME: | 486 case EVENT_TIME: |
475 case OTHER_TIME: | 487 case OTHER_TIME: |
| 488 case PREV_TIME: |
476 *num = the_event->timestamp; | 489 *num = the_event->timestamp; |
477 return true; | 490 return true; |
478 case EVENT_DURATION: | 491 case EVENT_DURATION: |
479 if (!the_event->has_other_event()) | 492 if (!the_event->has_other_event()) |
480 return false; | 493 return false; |
481 *num = the_event->GetAbsTimeToOtherEvent(); | 494 *num = the_event->GetAbsTimeToOtherEvent(); |
482 return true; | 495 return true; |
483 case EVENT_COMPLETE_DURATION: | 496 case EVENT_COMPLETE_DURATION: |
484 if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE) | 497 if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE) |
485 return false; | 498 return false; |
486 *num = the_event->duration; | 499 *num = the_event->duration; |
487 return true; | 500 return true; |
488 case EVENT_PHASE: | 501 case EVENT_PHASE: |
489 case OTHER_PHASE: | 502 case OTHER_PHASE: |
| 503 case PREV_PHASE: |
490 *num = static_cast<double>(the_event->phase); | 504 *num = static_cast<double>(the_event->phase); |
491 return true; | 505 return true; |
492 case EVENT_HAS_STRING_ARG: | 506 case EVENT_HAS_STRING_ARG: |
493 case OTHER_HAS_STRING_ARG: | 507 case OTHER_HAS_STRING_ARG: |
| 508 case PREV_HAS_STRING_ARG: |
494 *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0); | 509 *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0); |
495 return true; | 510 return true; |
496 case EVENT_HAS_NUMBER_ARG: | 511 case EVENT_HAS_NUMBER_ARG: |
497 case OTHER_HAS_NUMBER_ARG: | 512 case OTHER_HAS_NUMBER_ARG: |
| 513 case PREV_HAS_NUMBER_ARG: |
498 *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0); | 514 *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0); |
499 return true; | 515 return true; |
500 case EVENT_ARG: | 516 case EVENT_ARG: |
501 case OTHER_ARG: { | 517 case OTHER_ARG: |
| 518 case PREV_ARG: { |
502 // Search for the argument name and return its value if found. | 519 // Search for the argument name and return its value if found. |
503 std::map<std::string, double>::const_iterator num_i = | 520 std::map<std::string, double>::const_iterator num_i = |
504 the_event->arg_numbers.find(string_); | 521 the_event->arg_numbers.find(string_); |
505 if (num_i == the_event->arg_numbers.end()) | 522 if (num_i == the_event->arg_numbers.end()) |
506 return false; | 523 return false; |
507 *num = num_i->second; | 524 *num = num_i->second; |
508 return true; | 525 return true; |
509 } | 526 } |
510 case EVENT_HAS_OTHER: | 527 case EVENT_HAS_OTHER: |
511 // return 1.0 (true) if the other event exists | 528 // return 1.0 (true) if the other event exists |
512 *num = event.other_event ? 1.0 : 0.0; | 529 *num = event.other_event ? 1.0 : 0.0; |
513 return true; | 530 return true; |
| 531 case EVENT_HAS_PREV: |
| 532 *num = event.prev_event ? 1.0 : 0.0; |
| 533 return true; |
514 default: | 534 default: |
515 return false; | 535 return false; |
516 } | 536 } |
517 } | 537 } |
518 | 538 |
519 bool Query::GetMemberValueAsString(const TraceEvent& event, | 539 bool Query::GetMemberValueAsString(const TraceEvent& event, |
520 std::string* str) const { | 540 std::string* str) const { |
521 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); | 541 DCHECK_EQ(QUERY_EVENT_MEMBER, type_); |
522 | 542 |
523 // This could be a request for a member of |event| or a member of |event|'s | 543 // This could be a request for a member of |event| or a member of |event|'s |
524 // associated event. Store the target event in the_event: | 544 // associated previous or next event. Store the target event in the_event: |
525 const TraceEvent* the_event = (member_ < OTHER_PID) ? | 545 const TraceEvent* the_event = SelectTargetEvent(&event, member_); |
526 &event : event.other_event; | |
527 | 546 |
528 // Request for member of associated event, but there is no associated event. | 547 // Request for member of associated event, but there is no associated event. |
529 if (!the_event) | 548 if (!the_event) |
530 return false; | 549 return false; |
531 | 550 |
532 switch (member_) { | 551 switch (member_) { |
533 case EVENT_CATEGORY: | 552 case EVENT_CATEGORY: |
534 case OTHER_CATEGORY: | 553 case OTHER_CATEGORY: |
| 554 case PREV_CATEGORY: |
535 *str = the_event->category; | 555 *str = the_event->category; |
536 return true; | 556 return true; |
537 case EVENT_NAME: | 557 case EVENT_NAME: |
538 case OTHER_NAME: | 558 case OTHER_NAME: |
| 559 case PREV_NAME: |
539 *str = the_event->name; | 560 *str = the_event->name; |
540 return true; | 561 return true; |
541 case EVENT_ID: | 562 case EVENT_ID: |
542 case OTHER_ID: | 563 case OTHER_ID: |
| 564 case PREV_ID: |
543 *str = the_event->id; | 565 *str = the_event->id; |
544 return true; | 566 return true; |
545 case EVENT_ARG: | 567 case EVENT_ARG: |
546 case OTHER_ARG: { | 568 case OTHER_ARG: |
| 569 case PREV_ARG: { |
547 // Search for the argument name and return its value if found. | 570 // Search for the argument name and return its value if found. |
548 std::map<std::string, std::string>::const_iterator str_i = | 571 std::map<std::string, std::string>::const_iterator str_i = |
549 the_event->arg_strings.find(string_); | 572 the_event->arg_strings.find(string_); |
550 if (str_i == the_event->arg_strings.end()) | 573 if (str_i == the_event->arg_strings.end()) |
551 return false; | 574 return false; |
552 *str = str_i->second; | 575 *str = str_i->second; |
553 return true; | 576 return true; |
554 } | 577 } |
555 default: | 578 default: |
556 return false; | 579 return false; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN)); | 756 Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN)); |
734 Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END)); | 757 Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END)); |
735 Query match(Query::EventName() == Query::OtherName() && | 758 Query match(Query::EventName() == Query::OtherName() && |
736 Query::EventCategory() == Query::OtherCategory() && | 759 Query::EventCategory() == Query::OtherCategory() && |
737 Query::EventTid() == Query::OtherTid() && | 760 Query::EventTid() == Query::OtherTid() && |
738 Query::EventPid() == Query::OtherPid()); | 761 Query::EventPid() == Query::OtherPid()); |
739 | 762 |
740 AssociateEvents(begin, end, match); | 763 AssociateEvents(begin, end, match); |
741 } | 764 } |
742 | 765 |
743 void TraceAnalyzer::AssociateAsyncBeginEndEvents() { | 766 void TraceAnalyzer::AssociateAsyncBeginEndEvents(bool match_pid) { |
744 using trace_analyzer::Query; | 767 using trace_analyzer::Query; |
745 | 768 |
746 Query begin( | 769 Query begin( |
747 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || | 770 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || |
748 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || | 771 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || |
749 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); | 772 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); |
750 Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) || | 773 Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) || |
751 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || | 774 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || |
752 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); | 775 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); |
753 Query match(Query::EventName() == Query::OtherName() && | 776 Query match(Query::EventCategory() == Query::OtherCategory() && |
754 Query::EventCategory() == Query::OtherCategory() && | |
755 Query::EventId() == Query::OtherId()); | 777 Query::EventId() == Query::OtherId()); |
756 | 778 |
| 779 if (match_pid) { |
| 780 match = match && Query::EventPid() == Query::OtherPid(); |
| 781 } |
| 782 |
757 AssociateEvents(begin, end, match); | 783 AssociateEvents(begin, end, match); |
758 } | 784 } |
759 | 785 |
760 void TraceAnalyzer::AssociateEvents(const Query& first, | 786 void TraceAnalyzer::AssociateEvents(const Query& first, |
761 const Query& second, | 787 const Query& second, |
762 const Query& match) { | 788 const Query& match) { |
763 DCHECK(allow_assocation_changes_) | 789 DCHECK(allow_assocation_changes_) |
764 << "AssociateEvents not allowed after FindEvents"; | 790 << "AssociateEvents not allowed after FindEvents"; |
765 | 791 |
766 // Search for matching begin/end event pairs. When a matching end is found, | 792 // Search for matching begin/end event pairs. When a matching end is found, |
767 // it is associated with the begin event. | 793 // it is associated with the begin event. |
768 std::vector<TraceEvent*> begin_stack; | 794 std::vector<TraceEvent*> begin_stack; |
769 for (size_t event_index = 0; event_index < raw_events_.size(); | 795 for (size_t event_index = 0; event_index < raw_events_.size(); |
770 ++event_index) { | 796 ++event_index) { |
771 | 797 |
772 TraceEvent& this_event = raw_events_[event_index]; | 798 TraceEvent& this_event = raw_events_[event_index]; |
773 | 799 |
774 if (second.Evaluate(this_event)) { | 800 if (second.Evaluate(this_event)) { |
775 // Search stack for matching begin, starting from end. | 801 // Search stack for matching begin, starting from end. |
776 for (int stack_index = static_cast<int>(begin_stack.size()) - 1; | 802 for (int stack_index = static_cast<int>(begin_stack.size()) - 1; |
777 stack_index >= 0; --stack_index) { | 803 stack_index >= 0; --stack_index) { |
778 TraceEvent& begin_event = *begin_stack[stack_index]; | 804 TraceEvent& begin_event = *begin_stack[stack_index]; |
779 | 805 |
780 // Temporarily set other to test against the match query. | 806 // Temporarily set other to test against the match query. |
781 const TraceEvent* other_backup = begin_event.other_event; | 807 const TraceEvent* other_backup = begin_event.other_event; |
782 begin_event.other_event = &this_event; | 808 begin_event.other_event = &this_event; |
783 if (match.Evaluate(begin_event)) { | 809 if (match.Evaluate(begin_event)) { |
784 // Found a matching begin/end pair. | 810 // Found a matching begin/end pair. |
| 811 // Set the associated previous event |
| 812 this_event.prev_event = &begin_event; |
785 // Erase the matching begin event index from the stack. | 813 // Erase the matching begin event index from the stack. |
786 begin_stack.erase(begin_stack.begin() + stack_index); | 814 begin_stack.erase(begin_stack.begin() + stack_index); |
787 break; | 815 break; |
788 } | 816 } |
789 | 817 |
790 // Not a match, restore original other and continue. | 818 // Not a match, restore original other and continue. |
791 begin_event.other_event = other_backup; | 819 begin_event.other_event = other_backup; |
792 } | 820 } |
793 } | 821 } |
794 // Even if this_event is a |second| event that has matched an earlier | 822 // Even if this_event is a |second| event that has matched an earlier |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 end_position = (end_position < events.size()) ? end_position : events.size(); | 1018 end_position = (end_position < events.size()) ? end_position : events.size(); |
991 size_t count = 0u; | 1019 size_t count = 0u; |
992 for (size_t i = begin_position; i < end_position; ++i) { | 1020 for (size_t i = begin_position; i < end_position; ++i) { |
993 if (query.Evaluate(*events.at(i))) | 1021 if (query.Evaluate(*events.at(i))) |
994 ++count; | 1022 ++count; |
995 } | 1023 } |
996 return count; | 1024 return count; |
997 } | 1025 } |
998 | 1026 |
999 } // namespace trace_analyzer | 1027 } // namespace trace_analyzer |
OLD | NEW |