Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: runtime/vm/profiler_service.cc

Issue 965593002: Improved profiler view and inclusive profile tree (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/profiler.cc ('k') | runtime/vm/scope_timer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/profiler_service.h" 5 #include "vm/profiler_service.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/native_symbol.h" 8 #include "vm/native_symbol.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/os.h" 10 #include "vm/os.h"
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 if (exclusive) { 189 if (exclusive) {
190 exclusive_ticks_++; 190 exclusive_ticks_++;
191 } else { 191 } else {
192 inclusive_ticks_++; 192 inclusive_ticks_++;
193 // Mark the last serial we ticked the inclusive count. 193 // Mark the last serial we ticked the inclusive count.
194 inclusive_tick_serial_ = serial; 194 inclusive_tick_serial_ = serial;
195 } 195 }
196 } 196 }
197 197
198 void PrintToJSONObject(JSONObject* func) { 198 void PrintToJSONObject(JSONObject* func) {
199 if (kind() == kNativeFunction) { 199 func->AddProperty("type", "@Function");
200 func->AddProperty("type", "@Function"); 200 func->AddProperty("name", name());
201 func->AddProperty("name", name()); 201 func->AddProperty("kind", KindToCString(kind()));
202 func->AddProperty("kind", "Native");
203 } else if (kind() == kTagFunction) {
204 func->AddProperty("type", "@Function");
205 func->AddProperty("kind", "Tag");
206 func->AddProperty("name", name());
207 } else if (kind() == kUnkownFunction) {
208 func->AddProperty("type", "@Function");
209 func->AddProperty("name", name());
210 func->AddProperty("kind", "Collected");
211 } else if (kind() == kStubFunction) {
212 func->AddProperty("type", "@Function");
213 func->AddProperty("name", name());
214 func->AddProperty("kind", "Stub");
215 } else {
216 UNREACHABLE();
217 }
218 } 202 }
219 203
220 void PrintToJSONArray(JSONArray* functions) { 204 void PrintToJSONArray(JSONArray* functions) {
221 JSONObject obj(functions); 205 JSONObject obj(functions);
222 obj.AddProperty("kind", KindToCString(kind())); 206 obj.AddProperty("kind", KindToCString(kind()));
223 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); 207 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks());
224 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); 208 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks());
225 if (kind() == kDartFunction) { 209 if (kind() == kDartFunction) {
226 ASSERT(!function_.IsNull()); 210 ASSERT(!function_.IsNull());
227 obj.AddProperty("function", function_); 211 obj.AddProperty("function", function_);
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 // Generate a fake function entry. 607 // Generate a fake function entry.
624 JSONObject func(&obj, "function"); 608 JSONObject func(&obj, "function");
625 profile_function_->PrintToJSONObject(&func); 609 profile_function_->PrintToJSONObject(&func);
626 } 610 }
627 } 611 }
628 612
629 void PrintOverwrittenCode(JSONObject* profile_code_obj) { 613 void PrintOverwrittenCode(JSONObject* profile_code_obj) {
630 ASSERT(kind() == kReusedCode); 614 ASSERT(kind() == kReusedCode);
631 JSONObject obj(profile_code_obj, "code"); 615 JSONObject obj(profile_code_obj, "code");
632 obj.AddProperty("type", "@Code"); 616 obj.AddProperty("type", "@Code");
633 obj.AddProperty("kind", "Reused"); 617 obj.AddProperty("kind", "Collected");
634 obj.AddProperty("name", name()); 618 obj.AddProperty("name", name());
635 obj.AddPropertyF("start", "%" Px "", start()); 619 obj.AddPropertyF("start", "%" Px "", start());
636 obj.AddPropertyF("end", "%" Px "", end()); 620 obj.AddPropertyF("end", "%" Px "", end());
637 { 621 {
638 // Generate a fake function entry. 622 // Generate a fake function entry.
639 JSONObject func(&obj, "function"); 623 JSONObject func(&obj, "function");
640 ASSERT(profile_function_ != NULL); 624 ASSERT(profile_function_ != NULL);
641 profile_function_->PrintToJSONObject(&func); 625 profile_function_->PrintToJSONObject(&func);
642 } 626 }
643 } 627 }
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 return (*b)->count() - (*a)->count(); 1371 return (*b)->count() - (*a)->count();
1388 } 1372 }
1389 1373
1390 const intptr_t profile_function_table_index_; 1374 const intptr_t profile_function_table_index_;
1391 intptr_t count_; 1375 intptr_t count_;
1392 ZoneGrowableArray<ProfileFunctionTrieNode*> children_; 1376 ZoneGrowableArray<ProfileFunctionTrieNode*> children_;
1393 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_; 1377 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_;
1394 }; 1378 };
1395 1379
1396 1380
1397 class ProfileFunctionExclusiveTrieBuilder : public SampleVisitor { 1381 class ProfileFunctionTrieBuilder : public SampleVisitor {
1398 public: 1382 public:
1399 ProfileFunctionExclusiveTrieBuilder(Isolate* isolate, 1383 ProfileFunctionTrieBuilder(Isolate* isolate,
1400 CodeRegionTable* live_code_table, 1384 CodeRegionTable* live_code_table,
1401 CodeRegionTable* dead_code_table, 1385 CodeRegionTable* dead_code_table,
1402 CodeRegionTable* tag_code_table, 1386 CodeRegionTable* tag_code_table,
1403 ProfileFunctionTable* function_table) 1387 ProfileFunctionTable* function_table)
1404 : SampleVisitor(isolate), 1388 : SampleVisitor(isolate),
1405 live_code_table_(live_code_table), 1389 live_code_table_(live_code_table),
1406 dead_code_table_(dead_code_table), 1390 dead_code_table_(dead_code_table),
1407 tag_code_table_(tag_code_table), 1391 tag_code_table_(tag_code_table),
1408 function_table_(function_table), 1392 function_table_(function_table),
1393 inclusive_(false),
1409 trace_(false), 1394 trace_(false),
1410 trace_code_filter_(NULL) { 1395 trace_code_filter_(NULL) {
1411 ASSERT(live_code_table_ != NULL); 1396 ASSERT(live_code_table_ != NULL);
1412 ASSERT(dead_code_table_ != NULL); 1397 ASSERT(dead_code_table_ != NULL);
1413 ASSERT(tag_code_table_ != NULL); 1398 ASSERT(tag_code_table_ != NULL);
1414 ASSERT(function_table_ != NULL); 1399 ASSERT(function_table_ != NULL);
1415 set_tag_order(ProfilerService::kUserVM); 1400 set_tag_order(ProfilerService::kUserVM);
1416 1401
1417 intptr_t root_index = tag_code_table_->FindIndex(0); 1402 intptr_t root_index = tag_code_table_->FindIndex(0);
1418 // Verify that the "0" tag does exist. 1403 // Verify that the "0" tag does exist.
1419 ASSERT(root_index >= 0); 1404 ASSERT(root_index >= 0);
1420 CodeRegion* region = tag_code_table_->At(root_index); 1405 CodeRegion* region = tag_code_table_->At(root_index);
1421 ASSERT(region != NULL); 1406 ASSERT(region != NULL);
1407 ProfileFunction* function = region->function();
1408 ASSERT(function != NULL);
1422 1409
1423 ProfileFunction* function = region->function(); 1410 exclusive_root_ = new ProfileFunctionTrieNode(function->index());
1424 root_ = new ProfileFunctionTrieNode(function->index()); 1411 inclusive_root_ = new ProfileFunctionTrieNode(function->index());
1425 } 1412 }
1426 1413
1427 void VisitSample(Sample* sample) { 1414 void VisitSample(Sample* sample) {
1415 inclusive_ = false;
1416 ProcessSampleExclusive(sample);
1417 inclusive_ = true;
1418 ProcessSampleInclusive(sample);
1419 }
1420
1421 ProfileFunctionTrieNode* exclusive_root() const {
1422 return exclusive_root_;
1423 }
1424
1425 ProfileFunctionTrieNode* inclusive_root() const {
1426 return inclusive_root_;
1427 }
1428
1429 ProfilerService::TagOrder tag_order() const {
1430 return tag_order_;
1431 }
1432
1433 void set_tag_order(ProfilerService::TagOrder tag_order) {
1434 tag_order_ = tag_order;
1435 }
1436
1437 private:
1438 void ProcessSampleInclusive(Sample* sample) {
1428 // Give the root a tick. 1439 // Give the root a tick.
1429 root_->Tick(); 1440 inclusive_root_->Tick();
1430 ProfileFunctionTrieNode* current = root_; 1441 ProfileFunctionTrieNode* current = inclusive_root_;
1431 current = ProcessTags(sample, current); 1442 current = ProcessTags(sample, current);
1432 // Walk the sampled PCs. 1443 // Walk the sampled PCs.
1433 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1444 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) {
1434 if (sample->At(i) == 0) { 1445 if (sample->At(i) == 0) {
1435 break; 1446 continue;
1436 } 1447 }
1437 // If we aren't sampled out of an exit frame and this is the top 1448 // If we aren't sampled out of an exit frame and this is the top
1438 // frame. 1449 // frame.
1439 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); 1450 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample();
1440 current = ProcessPC(sample->At(i), sample->timestamp(), current, 1451 current = ProcessPC(sample->At(i), sample->timestamp(), current,
1441 visited(), exclusive_tick, 1452 visited(), exclusive_tick,
1442 sample->missing_frame_inserted()); 1453 sample->missing_frame_inserted());
1443 } 1454 }
1444 } 1455 }
1445 1456
1446 ProfileFunctionTrieNode* root() const { 1457 void ProcessSampleExclusive(Sample* sample) {
1447 return root_; 1458 // Give the root a tick.
1459 exclusive_root_->Tick();
1460 ProfileFunctionTrieNode* current = exclusive_root_;
1461 current = ProcessTags(sample, current);
1462 // Walk the sampled PCs.
1463 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1464 if (sample->At(i) == 0) {
1465 break;
1466 }
1467 // If we aren't sampled out of an exit frame and this is the top
1468 // frame.
1469 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample();
1470 current = ProcessPC(sample->At(i), sample->timestamp(), current,
1471 visited(), exclusive_tick,
1472 sample->missing_frame_inserted());
1473 }
1448 } 1474 }
1449 1475
1450 ProfilerService::TagOrder tag_order() const {
1451 return tag_order_;
1452 }
1453
1454 void set_tag_order(ProfilerService::TagOrder tag_order) {
1455 tag_order_ = tag_order;
1456 }
1457
1458 private:
1459 ProfileFunctionTrieNode* ProcessUserTags(Sample* sample, 1476 ProfileFunctionTrieNode* ProcessUserTags(Sample* sample,
1460 ProfileFunctionTrieNode* current) { 1477 ProfileFunctionTrieNode* current) {
1461 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 1478 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
1462 if (user_tag_index >= 0) { 1479 if (user_tag_index >= 0) {
1463 current = current->GetChild(user_tag_index); 1480 current = current->GetChild(user_tag_index);
1464 // Give the tag a tick. 1481 // Give the tag a tick.
1465 current->Tick(); 1482 current->Tick();
1466 } 1483 }
1467 return current; 1484 return current;
1468 } 1485 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 code.GetInlinedFunctionsAt(offset, &inlined_functions); 1579 code.GetInlinedFunctionsAt(offset, &inlined_functions);
1563 } 1580 }
1564 if (code.IsNull() || (inlined_functions.length() == 0)) { 1581 if (code.IsNull() || (inlined_functions.length() == 0)) {
1565 // No inlined functions. 1582 // No inlined functions.
1566 ProfileFunction* function = region->function(); 1583 ProfileFunction* function = region->function();
1567 ASSERT(function != NULL); 1584 ASSERT(function != NULL);
1568 if (trace_) { 1585 if (trace_) {
1569 OS::Print("[%" Px "] X - %s (%s)\n", 1586 OS::Print("[%" Px "] X - %s (%s)\n",
1570 pc, function->name(), region_name); 1587 pc, function->name(), region_name);
1571 } 1588 }
1572 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); 1589 if (!inclusive_) {
1590 function->Tick(exclusive, exclusive ? -1 : inclusive_serial);
1591 }
1573 current = current->GetChild(function->index()); 1592 current = current->GetChild(function->index());
1574 current->AddCodeObjectIndex(code_index); 1593 current->AddCodeObjectIndex(code_index);
1575 current->Tick(); 1594 current->Tick();
1576 if ((trace_code_filter_ != NULL) && 1595 if ((trace_code_filter_ != NULL) &&
1577 (strstr(region_name, trace_code_filter_) != NULL)) { 1596 (strstr(region_name, trace_code_filter_) != NULL)) {
1578 trace_ = true; 1597 trace_ = true;
1579 OS::Print("Tracing from: %" Px " [%s] ", pc, 1598 OS::Print("Tracing from: %" Px " [%s] ", pc,
1580 missing_frame_inserted ? "INSERTED" : ""); 1599 missing_frame_inserted ? "INSERTED" : "");
1581 Dump(current); 1600 Dump(current);
1582 } 1601 }
1583 return current; 1602 return current;
1584 } 1603 }
1585 1604
1586 1605 if (inclusive_) {
1587 for (intptr_t i = 0; i < inlined_functions.length(); i++) { 1606 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) {
1588 Function* inlined_function = inlined_functions[i]; 1607 Function* inlined_function = inlined_functions[i];
1589 ASSERT(inlined_function != NULL); 1608 ASSERT(inlined_function != NULL);
1590 ASSERT(!inlined_function->IsNull()); 1609 ASSERT(!inlined_function->IsNull());
1591 const char* inline_name = inlined_function->ToQualifiedCString(); 1610 current = ProcessInlinedFunction(
1592 if (trace_) { 1611 inlined_function, current, inclusive_serial, exclusive, code_index);
1593 OS::Print("[%" Px "] %" Pd " - %s (%s)\n", 1612 exclusive = false;
1613 }
1614 } else {
1615 for (intptr_t i = 0; i < inlined_functions.length(); i++) {
1616 Function* inlined_function = inlined_functions[i];
1617 ASSERT(inlined_function != NULL);
1618 ASSERT(!inlined_function->IsNull());
1619 const char* inline_name = inlined_function->ToQualifiedCString();
1620 if (trace_) {
1621 OS::Print("[%" Px "] %" Pd " - %s (%s)\n",
1594 pc, i, inline_name, region_name); 1622 pc, i, inline_name, region_name);
1595 } 1623 }
1596 ProfileFunction* function = 1624 current = ProcessInlinedFunction(
1597 function_table_->LookupOrAdd(*inlined_function); 1625 inlined_function, current, inclusive_serial, exclusive, code_index);
1598 ASSERT(function != NULL); 1626 exclusive = false;
1599 function->AddCodeObjectIndex(code_index); 1627 if ((trace_code_filter_ != NULL) &&
1600 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); 1628 (strstr(region_name, trace_code_filter_) != NULL)) {
1601 exclusive = false; 1629 trace_ = true;
1602 current = current->GetChild(function->index()); 1630 OS::Print("Tracing from: %" Px " [%s] ",
1603 current->AddCodeObjectIndex(code_index); 1631 pc, missing_frame_inserted ? "INSERTED" : "");
1604 current->Tick(); 1632 Dump(current);
1605 if ((trace_code_filter_ != NULL) && 1633 }
1606 (strstr(region_name, trace_code_filter_) != NULL)) {
1607 trace_ = true;
1608 OS::Print("Tracing from: %" Px " [%s] ",
1609 pc, missing_frame_inserted ? "INSERTED" : "");
1610 Dump(current);
1611 } 1634 }
1612 } 1635 }
1636
1613 return current; 1637 return current;
1614 } 1638 }
1615 1639
1640 ProfileFunctionTrieNode* ProcessInlinedFunction(
1641 Function* inlined_function,
1642 ProfileFunctionTrieNode* current,
1643 intptr_t inclusive_serial,
1644 bool exclusive,
1645 intptr_t code_index) {
1646 ProfileFunction* function =
1647 function_table_->LookupOrAdd(*inlined_function);
1648 ASSERT(function != NULL);
1649 function->AddCodeObjectIndex(code_index);
1650 function->Tick(exclusive, exclusive ? -1 : inclusive_serial);
1651 current = current->GetChild(function->index());
1652 current->AddCodeObjectIndex(code_index);
1653 current->Tick();
1654 return current;
1655 }
1656
1616 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const { 1657 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const {
1617 intptr_t index = live_code_table_->FindIndex(pc); 1658 intptr_t index = live_code_table_->FindIndex(pc);
1618 if (index < 0) { 1659 if (index < 0) {
1619 return NULL; 1660 return NULL;
1620 } 1661 }
1621 CodeRegion* region = live_code_table_->At(index); 1662 CodeRegion* region = live_code_table_->At(index);
1622 ASSERT(region->contains(pc)); 1663 ASSERT(region->contains(pc));
1623 if (region->compile_timestamp() > timestamp) { 1664 if (region->compile_timestamp() > timestamp) {
1624 // Overwritten code, find in dead code table. 1665 // Overwritten code, find in dead code table.
1625 index = dead_code_table_->FindIndex(pc); 1666 index = dead_code_table_->FindIndex(pc);
1626 if (index < 0) { 1667 if (index < 0) {
1627 return NULL; 1668 return NULL;
1628 } 1669 }
1629 region = dead_code_table_->At(index); 1670 region = dead_code_table_->At(index);
1630 ASSERT(region->contains(pc)); 1671 ASSERT(region->contains(pc));
1631 ASSERT(region->compile_timestamp() <= timestamp); 1672 ASSERT(region->compile_timestamp() <= timestamp);
1632 return region; 1673 return region;
1633 } 1674 }
1634 ASSERT(region->compile_timestamp() <= timestamp); 1675 ASSERT(region->compile_timestamp() <= timestamp);
1635 return region; 1676 return region;
1636 } 1677 }
1637 1678
1638 ProfilerService::TagOrder tag_order_; 1679 ProfilerService::TagOrder tag_order_;
1639 ProfileFunctionTrieNode* root_; 1680 ProfileFunctionTrieNode* exclusive_root_;
1681 ProfileFunctionTrieNode* inclusive_root_;
1640 CodeRegionTable* live_code_table_; 1682 CodeRegionTable* live_code_table_;
1641 CodeRegionTable* dead_code_table_; 1683 CodeRegionTable* dead_code_table_;
1642 CodeRegionTable* tag_code_table_; 1684 CodeRegionTable* tag_code_table_;
1643 ProfileFunctionTable* function_table_; 1685 ProfileFunctionTable* function_table_;
1686 bool inclusive_;
1644 bool trace_; 1687 bool trace_;
1645 const char* trace_code_filter_; 1688 const char* trace_code_filter_;
1646 }; 1689 };
1647 1690
1648 1691
1649 class CodeRegionTrieNode : public ZoneAllocated { 1692 class CodeRegionTrieNode : public ZoneAllocated {
1650 public: 1693 public:
1651 explicit CodeRegionTrieNode(intptr_t code_region_index) 1694 explicit CodeRegionTrieNode(intptr_t code_region_index)
1652 : code_region_index_(code_region_index), 1695 : code_region_index_(code_region_index),
1653 count_(0), 1696 count_(0),
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1731 ASSERT(b != NULL); 1774 ASSERT(b != NULL);
1732 return (*b)->count() - (*a)->count(); 1775 return (*b)->count() - (*a)->count();
1733 } 1776 }
1734 1777
1735 const intptr_t code_region_index_; 1778 const intptr_t code_region_index_;
1736 intptr_t count_; 1779 intptr_t count_;
1737 ZoneGrowableArray<CodeRegionTrieNode*>* children_; 1780 ZoneGrowableArray<CodeRegionTrieNode*>* children_;
1738 }; 1781 };
1739 1782
1740 1783
1741 class CodeRegionExclusiveTrieBuilder : public SampleVisitor { 1784 class CodeRegionTrieBuilder : public SampleVisitor {
1742 public: 1785 public:
1743 CodeRegionExclusiveTrieBuilder(Isolate* isolate, 1786 CodeRegionTrieBuilder(Isolate* isolate,
1744 CodeRegionTable* live_code_table, 1787 CodeRegionTable* live_code_table,
1745 CodeRegionTable* dead_code_table, 1788 CodeRegionTable* dead_code_table,
1746 CodeRegionTable* tag_code_table) 1789 CodeRegionTable* tag_code_table)
1747 : SampleVisitor(isolate), 1790 : SampleVisitor(isolate),
1748 live_code_table_(live_code_table), 1791 live_code_table_(live_code_table),
1749 dead_code_table_(dead_code_table), 1792 dead_code_table_(dead_code_table),
1750 tag_code_table_(tag_code_table) { 1793 tag_code_table_(tag_code_table) {
1751 ASSERT(live_code_table_ != NULL); 1794 ASSERT(live_code_table_ != NULL);
1752 ASSERT(dead_code_table_ != NULL); 1795 ASSERT(dead_code_table_ != NULL);
1753 ASSERT(tag_code_table_ != NULL); 1796 ASSERT(tag_code_table_ != NULL);
1754 set_tag_order(ProfilerService::kUserVM); 1797 set_tag_order(ProfilerService::kUserVM);
1755 1798
1756 intptr_t root_index = tag_code_table_->FindIndex(0); 1799 intptr_t root_index = tag_code_table_->FindIndex(0);
1757 // Verify that the "0" (root) tag does exist. 1800 // Verify that the "0" (root) tag does exist.
1758 ASSERT(root_index >= 0); 1801 ASSERT(root_index >= 0);
1759 CodeRegion* region = tag_code_table_->At(root_index); 1802 CodeRegion* region = tag_code_table_->At(root_index);
1760 ASSERT(region != NULL); 1803 ASSERT(region != NULL);
1761 root_ = new CodeRegionTrieNode(region->code_table_index()); 1804
1805 exclusive_root_ = new CodeRegionTrieNode(region->code_table_index());
1806 inclusive_root_ = new CodeRegionTrieNode(region->code_table_index());
1762 } 1807 }
1763 1808
1764 void VisitSample(Sample* sample) { 1809 void VisitSample(Sample* sample) {
1810 ProcessSampleExclusive(sample);
1811 ProcessSampleInclusive(sample);
1812 }
1813
1814 CodeRegionTrieNode* inclusive_root() const {
1815 return inclusive_root_;
1816 }
1817
1818 CodeRegionTrieNode* exclusive_root() const {
1819 return exclusive_root_;
1820 }
1821
1822 ProfilerService::TagOrder tag_order() const {
1823 return tag_order_;
1824 }
1825
1826 void set_tag_order(ProfilerService::TagOrder tag_order) {
1827 tag_order_ = tag_order;
1828 }
1829
1830 private:
1831 void ProcessSampleInclusive(Sample* sample) {
1765 // Give the root a tick. 1832 // Give the root a tick.
1766 root_->Tick(); 1833 inclusive_root_->Tick();
1767 CodeRegionTrieNode* current = root_; 1834 CodeRegionTrieNode* current = inclusive_root_;
1768 current = ProcessTags(sample, current); 1835 current = ProcessTags(sample, current);
1769 // Walk the sampled PCs. 1836 // Walk the sampled PCs.
1770 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1837 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) {
1771 if (sample->At(i) == 0) { 1838 if (sample->At(i) == 0) {
1772 break; 1839 continue;
1773 } 1840 }
1774 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); 1841 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
1775 if (index < 0) { 1842 if (index < 0) {
1776 continue; 1843 continue;
1777 } 1844 }
1778 current = current->GetChild(index); 1845 current = current->GetChild(index);
1779 current->Tick(); 1846 current->Tick();
1780 } 1847 }
1781 } 1848 }
1782 1849
1783 CodeRegionTrieNode* root() const { 1850 void ProcessSampleExclusive(Sample* sample) {
1784 return root_; 1851 // Give the root a tick.
1852 exclusive_root_->Tick();
1853 CodeRegionTrieNode* current = exclusive_root_;
1854 current = ProcessTags(sample, current);
1855 // Walk the sampled PCs.
1856 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1857 if (sample->At(i) == 0) {
1858 break;
1859 }
1860 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
1861 if (index < 0) {
1862 continue;
1863 }
1864 current = current->GetChild(index);
1865 current->Tick();
1866 }
1785 } 1867 }
1786 1868
1787 ProfilerService::TagOrder tag_order() const {
1788 return tag_order_;
1789 }
1790
1791 void set_tag_order(ProfilerService::TagOrder tag_order) {
1792 tag_order_ = tag_order;
1793 }
1794
1795 private:
1796 CodeRegionTrieNode* ProcessUserTags(Sample* sample, 1869 CodeRegionTrieNode* ProcessUserTags(Sample* sample,
1797 CodeRegionTrieNode* current) { 1870 CodeRegionTrieNode* current) {
1798 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 1871 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
1799 if (user_tag_index >= 0) { 1872 if (user_tag_index >= 0) {
1800 current = current->GetChild(user_tag_index); 1873 current = current->GetChild(user_tag_index);
1801 // Give the tag a tick. 1874 // Give the tag a tick.
1802 current->Tick(); 1875 current->Tick();
1803 } 1876 }
1804 return current; 1877 return current;
1805 } 1878 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 ASSERT(region->contains(pc)); 1963 ASSERT(region->contains(pc));
1891 if (region->compile_timestamp() > timestamp) { 1964 if (region->compile_timestamp() > timestamp) {
1892 // Overwritten code, find in dead code table. 1965 // Overwritten code, find in dead code table.
1893 return FindDeadIndex(pc, timestamp); 1966 return FindDeadIndex(pc, timestamp);
1894 } 1967 }
1895 ASSERT(region->compile_timestamp() <= timestamp); 1968 ASSERT(region->compile_timestamp() <= timestamp);
1896 return region->code_table_index(); 1969 return region->code_table_index();
1897 } 1970 }
1898 1971
1899 ProfilerService::TagOrder tag_order_; 1972 ProfilerService::TagOrder tag_order_;
1900 CodeRegionTrieNode* root_; 1973 CodeRegionTrieNode* exclusive_root_;
1974 CodeRegionTrieNode* inclusive_root_;
1901 CodeRegionTable* live_code_table_; 1975 CodeRegionTable* live_code_table_;
1902 CodeRegionTable* dead_code_table_; 1976 CodeRegionTable* dead_code_table_;
1903 CodeRegionTable* tag_code_table_; 1977 CodeRegionTable* tag_code_table_;
1904 }; 1978 };
1905 1979
1906 1980
1907 void ProfilerService::PrintJSON(JSONStream* stream, TagOrder tag_order) { 1981 void ProfilerService::PrintJSON(JSONStream* stream, TagOrder tag_order) {
1908 Isolate* isolate = Isolate::Current(); 1982 Isolate* isolate = Isolate::Current();
1909 // Disable profile interrupts while processing the buffer. 1983 // Disable profile interrupts while processing the buffer.
1910 Profiler::EndExecution(isolate); 1984 Profiler::EndExecution(isolate);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1976 CodeRegionFunctionMapper mapper(isolate, &live_code_table, 2050 CodeRegionFunctionMapper mapper(isolate, &live_code_table,
1977 &dead_code_table, 2051 &dead_code_table,
1978 &tag_code_table, 2052 &tag_code_table,
1979 &function_table); 2053 &function_table);
1980 mapper.Map(); 2054 mapper.Map();
1981 } 2055 }
1982 if (FLAG_trace_profiler) { 2056 if (FLAG_trace_profiler) {
1983 intptr_t total_functions = function_table.Length(); 2057 intptr_t total_functions = function_table.Length();
1984 OS::Print("FunctionTable: size=%" Pd "\n", total_functions); 2058 OS::Print("FunctionTable: size=%" Pd "\n", total_functions);
1985 } 2059 }
1986 CodeRegionExclusiveTrieBuilder code_trie_builder(isolate, 2060 CodeRegionTrieBuilder code_trie_builder(isolate,
1987 &live_code_table, 2061 &live_code_table,
1988 &dead_code_table, 2062 &dead_code_table,
1989 &tag_code_table); 2063 &tag_code_table);
1990 code_trie_builder.set_tag_order(tag_order); 2064 code_trie_builder.set_tag_order(tag_order);
1991 { 2065 {
1992 // Build CodeRegion trie. 2066 // Build CodeRegion trie.
1993 ScopeTimer sw("CodeRegionExclusiveTrieBuilder", FLAG_trace_profiler); 2067 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler);
1994 sample_buffer->VisitSamples(&code_trie_builder); 2068 sample_buffer->VisitSamples(&code_trie_builder);
1995 code_trie_builder.root()->SortByCount(); 2069 code_trie_builder.exclusive_root()->SortByCount();
2070 code_trie_builder.inclusive_root()->SortByCount();
1996 } 2071 }
1997 ProfileFunctionExclusiveTrieBuilder 2072 ProfileFunctionTrieBuilder function_trie_builder(isolate,
1998 function_trie_builder(isolate, 2073 &live_code_table,
1999 &live_code_table, 2074 &dead_code_table,
2000 &dead_code_table, 2075 &tag_code_table,
2001 &tag_code_table, 2076 &function_table);
2002 &function_table);
2003 function_trie_builder.set_tag_order(tag_order); 2077 function_trie_builder.set_tag_order(tag_order);
2004 { 2078 {
2005 // Build ProfileFunction trie. 2079 // Build ProfileFunction trie.
2006 ScopeTimer sw("ProfileFunctionExclusiveTrieBuilder", 2080 ScopeTimer sw("ProfileFunctionTrieBuilder",
2007 FLAG_trace_profiler); 2081 FLAG_trace_profiler);
2008 sample_buffer->VisitSamples(&function_trie_builder); 2082 sample_buffer->VisitSamples(&function_trie_builder);
2009 function_trie_builder.root()->SortByCount(); 2083 function_trie_builder.exclusive_root()->SortByCount();
2084 function_trie_builder.inclusive_root()->SortByCount();
2010 } 2085 }
2011 { 2086 {
2012 ScopeTimer sw("CodeTableStream", FLAG_trace_profiler); 2087 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler);
2013 // Serialize to JSON. 2088 // Serialize to JSON.
2014 JSONObject obj(stream); 2089 JSONObject obj(stream);
2015 obj.AddProperty("type", "_CpuProfile"); 2090 obj.AddProperty("type", "_CpuProfile");
2016 obj.AddProperty("sampleCount", samples); 2091 obj.AddProperty("sampleCount", samples);
2017 obj.AddProperty("samplePeriod", 2092 obj.AddProperty("samplePeriod",
2018 static_cast<intptr_t>(FLAG_profile_period)); 2093 static_cast<intptr_t>(FLAG_profile_period));
2019 obj.AddProperty("stackDepth", 2094 obj.AddProperty("stackDepth",
2020 static_cast<intptr_t>(FLAG_profile_depth)); 2095 static_cast<intptr_t>(FLAG_profile_depth));
2021 obj.AddProperty("timeSpan", 2096 obj.AddProperty("timeSpan",
2022 MicrosecondsToSeconds(builder.TimeDeltaMicros())); 2097 MicrosecondsToSeconds(builder.TimeDeltaMicros()));
2023 { 2098 {
2024 JSONArray exclusive_trie(&obj, "exclusiveCodeTrie"); 2099 JSONArray code_trie(&obj, "exclusiveCodeTrie");
2025 CodeRegionTrieNode* root = code_trie_builder.root(); 2100 CodeRegionTrieNode* root = code_trie_builder.exclusive_root();
2026 ASSERT(root != NULL); 2101 ASSERT(root != NULL);
2027 root->PrintToJSONArray(&exclusive_trie); 2102 root->PrintToJSONArray(&code_trie);
2103 }
2104 {
2105 JSONArray code_trie(&obj, "inclusiveCodeTrie");
2106 CodeRegionTrieNode* root = code_trie_builder.inclusive_root();
2107 ASSERT(root != NULL);
2108 root->PrintToJSONArray(&code_trie);
2028 } 2109 }
2029 { 2110 {
2030 JSONArray function_trie(&obj, "exclusiveFunctionTrie"); 2111 JSONArray function_trie(&obj, "exclusiveFunctionTrie");
2031 ProfileFunctionTrieNode* root = function_trie_builder.root(); 2112 ProfileFunctionTrieNode* root =
2113 function_trie_builder.exclusive_root();
2032 ASSERT(root != NULL); 2114 ASSERT(root != NULL);
2033 root->PrintToJSONArray(&function_trie); 2115 root->PrintToJSONArray(&function_trie);
2034 } 2116 }
2117 {
2118 JSONArray function_trie(&obj, "inclusiveFunctionTrie");
2119 ProfileFunctionTrieNode* root =
2120 function_trie_builder.inclusive_root();
2121 ASSERT(root != NULL);
2122 root->PrintToJSONArray(&function_trie);
2123 }
2035 { 2124 {
2036 JSONArray codes(&obj, "codes"); 2125 JSONArray codes(&obj, "codes");
2037 for (intptr_t i = 0; i < live_code_table.Length(); i++) { 2126 for (intptr_t i = 0; i < live_code_table.Length(); i++) {
2038 CodeRegion* region = live_code_table.At(i); 2127 CodeRegion* region = live_code_table.At(i);
2039 ASSERT(region != NULL); 2128 ASSERT(region != NULL);
2040 region->PrintToJSONArray(&codes); 2129 region->PrintToJSONArray(&codes);
2041 } 2130 }
2042 for (intptr_t i = 0; i < dead_code_table.Length(); i++) { 2131 for (intptr_t i = 0; i < dead_code_table.Length(); i++) {
2043 CodeRegion* region = dead_code_table.At(i); 2132 CodeRegion* region = dead_code_table.At(i);
2044 ASSERT(region != NULL); 2133 ASSERT(region != NULL);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2083 ASSERT(sample_buffer != NULL); 2172 ASSERT(sample_buffer != NULL);
2084 2173
2085 ClearProfileVisitor clear_profile(isolate); 2174 ClearProfileVisitor clear_profile(isolate);
2086 sample_buffer->VisitSamples(&clear_profile); 2175 sample_buffer->VisitSamples(&clear_profile);
2087 2176
2088 // Enable profile interrupts. 2177 // Enable profile interrupts.
2089 Profiler::BeginExecution(isolate); 2178 Profiler::BeginExecution(isolate);
2090 } 2179 }
2091 2180
2092 } // namespace dart 2181 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.cc ('k') | runtime/vm/scope_timer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698