| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #ifndef BASE_TRACKED_OBJECTS_H_ | 5 #ifndef BASE_TRACKED_OBJECTS_H_ |
| 6 #define BASE_TRACKED_OBJECTS_H_ | 6 #define BASE_TRACKED_OBJECTS_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <stack> | 10 #include <stack> |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 return death_data_.run_duration_max(); | 333 return death_data_.run_duration_max(); |
| 334 } | 334 } |
| 335 DurationInt queue_duration() const { return death_data_.queue_duration(); } | 335 DurationInt queue_duration() const { return death_data_.queue_duration(); } |
| 336 DurationInt AverageMsQueueDuration() const { | 336 DurationInt AverageMsQueueDuration() const { |
| 337 return death_data_.AverageMsQueueDuration(); | 337 return death_data_.AverageMsQueueDuration(); |
| 338 } | 338 } |
| 339 DurationInt queue_duration_max() const { | 339 DurationInt queue_duration_max() const { |
| 340 return death_data_.queue_duration_max(); | 340 return death_data_.queue_duration_max(); |
| 341 } | 341 } |
| 342 | 342 |
| 343 // Emit contents for use in a line of HTML | |
| 344 void WriteHTML(std::string* output) const; | |
| 345 | |
| 346 // Construct a DictionaryValue instance containing all our data recursively. | 343 // Construct a DictionaryValue instance containing all our data recursively. |
| 347 // The caller assumes ownership of the memory in the returned instance. | 344 // The caller assumes ownership of the memory in the returned instance. |
| 348 base::DictionaryValue* ToValue() const; | 345 base::DictionaryValue* ToValue() const; |
| 349 | 346 |
| 350 private: | 347 private: |
| 351 const BirthOnThread* birth_; // Includes Location and birth_thread. | 348 const BirthOnThread* birth_; // Includes Location and birth_thread. |
| 352 const ThreadData* death_thread_; | 349 const ThreadData* death_thread_; |
| 353 DeathData death_data_; | 350 DeathData death_data_; |
| 354 }; | 351 }; |
| 355 | 352 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 | 391 |
| 395 // The total number of births recorded at each location for which we have not | 392 // The total number of births recorded at each location for which we have not |
| 396 // seen a death count. This map changes as we do Append() calls, and is later | 393 // seen a death count. This map changes as we do Append() calls, and is later |
| 397 // used by AddListOfLivingObjects() to gather up unaccounted for births. | 394 // used by AddListOfLivingObjects() to gather up unaccounted for births. |
| 398 BirthCount global_birth_count_; | 395 BirthCount global_birth_count_; |
| 399 | 396 |
| 400 DISALLOW_COPY_AND_ASSIGN(DataCollector); | 397 DISALLOW_COPY_AND_ASSIGN(DataCollector); |
| 401 }; | 398 }; |
| 402 | 399 |
| 403 //------------------------------------------------------------------------------ | 400 //------------------------------------------------------------------------------ |
| 404 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot | |
| 405 // instances to provide printing of these collections on a single line. | |
| 406 // We generally provide an aggregate total for the entire list, as well as | |
| 407 // aggregate subtotals for groups of stats (example: group of all lives that | |
| 408 // died on the specific thread). | |
| 409 | |
| 410 class BASE_EXPORT Aggregation: public DeathData { | |
| 411 public: | |
| 412 Aggregation(); | |
| 413 ~Aggregation(); | |
| 414 | |
| 415 void AddDeathSnapshot(const Snapshot& snapshot); | |
| 416 void AddBirths(const Births& births); | |
| 417 void AddBirth(const BirthOnThread& birth); | |
| 418 void AddBirthPlace(const Location& location); | |
| 419 void WriteHTML(std::string* output) const; | |
| 420 void Clear(); | |
| 421 | |
| 422 private: | |
| 423 int birth_count_; | |
| 424 std::map<std::string, int> birth_files_; | |
| 425 std::map<Location, int> locations_; | |
| 426 std::map<const ThreadData*, int> birth_threads_; | |
| 427 DeathData death_data_; | |
| 428 std::map<const ThreadData*, int> death_threads_; | |
| 429 | |
| 430 DISALLOW_COPY_AND_ASSIGN(Aggregation); | |
| 431 }; | |
| 432 | |
| 433 //------------------------------------------------------------------------------ | |
| 434 // Comparator is a class that supports the comparison of Snapshot instances. | |
| 435 // An instance is actually a list of chained Comparitors, that can provide for | |
| 436 // arbitrary ordering. The path portion of an about:profiler URL is translated | |
| 437 // into such a chain, which is then used to order Snapshot instances in a | |
| 438 // vector. It orders them into groups (for aggregation), and can also order | |
| 439 // instances within the groups (for detailed rendering of the instances in an | |
| 440 // aggregation). | |
| 441 | |
| 442 class BASE_EXPORT Comparator { | |
| 443 public: | |
| 444 // Selector enum is the token identifier for each parsed keyword, most of | |
| 445 // which specify a sort order. | |
| 446 // Since it is not meaningful to sort more than once on a specific key, we | |
| 447 // use bitfields to accumulate what we have sorted on so far. | |
| 448 enum Selector { | |
| 449 // Sort orders. | |
| 450 NIL = 0, | |
| 451 BIRTH_THREAD = 1, | |
| 452 DEATH_THREAD = 2, | |
| 453 BIRTH_FILE = 4, | |
| 454 BIRTH_FUNCTION = 8, | |
| 455 BIRTH_LINE = 16, | |
| 456 COUNT = 32, | |
| 457 AVERAGE_RUN_DURATION = 64, | |
| 458 TOTAL_RUN_DURATION = 128, | |
| 459 AVERAGE_QUEUE_DURATION = 256, | |
| 460 TOTAL_QUEUE_DURATION = 512, | |
| 461 MAX_RUN_DURATION = 1024, | |
| 462 MAX_QUEUE_DURATION = 2048, | |
| 463 | |
| 464 // Imediate action keywords. | |
| 465 RESET_ALL_DATA = -1, | |
| 466 UNKNOWN_KEYWORD = -2, | |
| 467 }; | |
| 468 | |
| 469 explicit Comparator(); | |
| 470 | |
| 471 // Reset the comparator to a NIL selector. Clear() and recursively delete any | |
| 472 // tiebreaker_ entries. NOTE: We can't use a standard destructor, because | |
| 473 // the sort algorithm makes copies of this object, and then deletes them, | |
| 474 // which would cause problems (either we'd make expensive deep copies, or we'd | |
| 475 // do more thna one delete on a tiebreaker_. | |
| 476 void Clear(); | |
| 477 | |
| 478 // The less() operator for sorting the array via std::sort(). | |
| 479 bool operator()(const Snapshot& left, const Snapshot& right) const; | |
| 480 | |
| 481 void Sort(DataCollector::Collection* collection) const; | |
| 482 | |
| 483 // Check to see if the items are sort equivalents (should be aggregated). | |
| 484 bool Equivalent(const Snapshot& left, const Snapshot& right) const; | |
| 485 | |
| 486 // Check to see if all required fields are present in the given sample. | |
| 487 bool Acceptable(const Snapshot& sample) const; | |
| 488 | |
| 489 // A comparator can be refined by specifying what to do if the selected basis | |
| 490 // for comparison is insufficient to establish an ordering. This call adds | |
| 491 // the indicated attribute as the new "least significant" basis of comparison. | |
| 492 void SetTiebreaker(Selector selector, const std::string& required); | |
| 493 | |
| 494 // Indicate if this instance is set up to sort by the given Selector, thereby | |
| 495 // putting that information in the SortGrouping, so it is not needed in each | |
| 496 // printed line. | |
| 497 bool IsGroupedBy(Selector selector) const; | |
| 498 | |
| 499 // Using the tiebreakers as set above, we mostly get an ordering, with some | |
| 500 // equivalent groups. If those groups are displayed (rather than just being | |
| 501 // aggregated, then the following is used to order them (within the group). | |
| 502 void SetSubgroupTiebreaker(Selector selector); | |
| 503 | |
| 504 // Translate a keyword and restriction in URL path to a selector for sorting. | |
| 505 void ParseKeyphrase(const std::string& key_phrase); | |
| 506 | |
| 507 // Parse a query to decide on sort ordering. | |
| 508 bool ParseQuery(const std::string& query); | |
| 509 | |
| 510 // Output a header line that can be used to indicated what items will be | |
| 511 // collected in the group. It lists all (potentially) tested attributes and | |
| 512 // their values (in the sample item). | |
| 513 bool WriteSortGrouping(const Snapshot& sample, std::string* output) const; | |
| 514 | |
| 515 // Output a sample, with SortGroup details not displayed. | |
| 516 void WriteSnapshotHTML(const Snapshot& sample, std::string* output) const; | |
| 517 | |
| 518 private: | |
| 519 // The selector directs this instance to compare based on the specified | |
| 520 // members of the tested elements. | |
| 521 enum Selector selector_; | |
| 522 | |
| 523 // Translate a path keyword into a selector. This is a slow implementation, | |
| 524 // but this is rarely done, and only for HTML presentations. | |
| 525 static Selector FindSelector(const std::string& keyword); | |
| 526 | |
| 527 // For filtering into acceptable and unacceptable snapshot instance, the | |
| 528 // following is required to be a substring of the selector_ field. | |
| 529 std::string required_; | |
| 530 | |
| 531 // If this instance can't decide on an ordering, we can consult a tie-breaker | |
| 532 // which may have a different basis of comparison. | |
| 533 Comparator* tiebreaker_; | |
| 534 | |
| 535 // We or together all the selectors we sort on (not counting sub-group | |
| 536 // selectors), so that we can tell if we've decided to group on any given | |
| 537 // criteria. | |
| 538 int combined_selectors_; | |
| 539 | |
| 540 // Some tiebreakrs are for subgroup ordering, and not for basic ordering (in | |
| 541 // preparation for aggregation). The subgroup tiebreakers are not consulted | |
| 542 // when deciding if two items are in equivalent groups. This flag tells us | |
| 543 // to ignore the tiebreaker when doing Equivalent() testing. | |
| 544 bool use_tiebreaker_for_sort_only_; | |
| 545 }; | |
| 546 | |
| 547 //------------------------------------------------------------------------------ | |
| 548 // For each thread, we have a ThreadData that stores all tracking info generated | 401 // For each thread, we have a ThreadData that stores all tracking info generated |
| 549 // on this thread. This prevents the need for locking as data accumulates. | 402 // on this thread. This prevents the need for locking as data accumulates. |
| 550 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 403 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 551 // We also have a linked list of ThreadData instances, and that list is used to | 404 // We also have a linked list of ThreadData instances, and that list is used to |
| 552 // harvest data from all existing instances. | 405 // harvest data from all existing instances. |
| 553 | 406 |
| 554 class BASE_EXPORT ThreadData { | 407 class BASE_EXPORT ThreadData { |
| 555 public: | 408 public: |
| 556 // Current allowable states of the tracking system. The states can vary | 409 // Current allowable states of the tracking system. The states can vary |
| 557 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. | 410 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 569 // set *before* any births on the threads have taken place. It is generally | 422 // set *before* any births on the threads have taken place. It is generally |
| 570 // only used by the message loop, which has a well defined thread name. | 423 // only used by the message loop, which has a well defined thread name. |
| 571 static void InitializeThreadContext(const std::string& suggested_name); | 424 static void InitializeThreadContext(const std::string& suggested_name); |
| 572 | 425 |
| 573 // Using Thread Local Store, find the current instance for collecting data. | 426 // Using Thread Local Store, find the current instance for collecting data. |
| 574 // If an instance does not exist, construct one (and remember it for use on | 427 // If an instance does not exist, construct one (and remember it for use on |
| 575 // this thread. | 428 // this thread. |
| 576 // This may return NULL if the system is disabled for any reason. | 429 // This may return NULL if the system is disabled for any reason. |
| 577 static ThreadData* Get(); | 430 static ThreadData* Get(); |
| 578 | 431 |
| 579 // For a given (unescaped) about:profiler query, develop resulting HTML, and | |
| 580 // append to output. | |
| 581 static void WriteHTML(const std::string& query, std::string* output); | |
| 582 | |
| 583 // For a given accumulated array of results, use the comparator to sort and | |
| 584 // subtotal, writing the results to the output. | |
| 585 static void WriteHTMLTotalAndSubtotals( | |
| 586 const DataCollector::Collection& match_array, | |
| 587 const Comparator& comparator, std::string* output); | |
| 588 | |
| 589 // Constructs a DictionaryValue instance containing all recursive results in | 432 // Constructs a DictionaryValue instance containing all recursive results in |
| 590 // our process. The caller assumes ownership of the memory in the returned | 433 // our process. The caller assumes ownership of the memory in the returned |
| 591 // instance. | 434 // instance. |
| 592 static base::DictionaryValue* ToValue(); | 435 static base::DictionaryValue* ToValue(); |
| 593 | 436 |
| 594 // Finds (or creates) a place to count births from the given location in this | 437 // Finds (or creates) a place to count births from the given location in this |
| 595 // thread, and increment that tally. | 438 // thread, and increment that tally. |
| 596 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. | 439 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. |
| 597 static Births* TallyABirthIfActive(const Location& location); | 440 static Births* TallyABirthIfActive(const Location& location); |
| 598 | 441 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 } | 661 } |
| 819 | 662 |
| 820 private: | 663 private: |
| 821 | 664 |
| 822 DISALLOW_COPY_AND_ASSIGN(AutoTracking); | 665 DISALLOW_COPY_AND_ASSIGN(AutoTracking); |
| 823 }; | 666 }; |
| 824 | 667 |
| 825 } // namespace tracked_objects | 668 } // namespace tracked_objects |
| 826 | 669 |
| 827 #endif // BASE_TRACKED_OBJECTS_H_ | 670 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |