blob: d76cb19ca950c79af49088a385ab5dd321fa0b79 [file] [log] [blame]
<link rel="import" href="../../../../packages/polymer/polymer.html">
<link rel="import" href="code_ref.html">
<link rel="import" href="function_ref.html">
<link rel="import" href="nav_bar.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="sliding_checkbox.html">
<link rel="import" href="view_footer.html">
<polymer-element name="sample-buffer-control" extends="observatory-element">
<template>
<link rel="stylesheet" href="css/shared.css">
<style>
.statusMessage {
font-size: 150%;
font-weight: bold;
}
.statusBox {
height: 100%;
padding: 1em;
}
.center {
align-items: center;
justify-content: center;
}
.notice {
background-color: #fcf8e3;
}
.red {
background-color: #f2dede;
}
</style>
<div class="content-centered-big">
<template if="{{ state != 'kNotLoaded' }}">
<h2>Sample buffer</h2>
<hr>
</template>
<template if="{{ state == 'kFetching' }}">
<div class="statusBox shadow center">
<div class="statusMessage">Fetching profile from VM...</div>
</div>
</template>
<template if="{{ state == 'kLoading' }}">
<div class="statusBox shadow center">
<div class="statusMessage">Loading profile...</div>
</div>
</template>
<template if="{{ state == 'kDisabled' }}">
<div class="statusBox shadow center">
<div>
<h1>Profiling is disabled</h1>
<br>
Perhaps the <b>profile</b> flag has been disabled for this VM.
<br><br>
See all
<a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
</div>
</div>
</template>
<template if="{{ state == 'kException' }}">
<div class="statusBox shadow center">
<div class="statusMessage">
<h1>Profiling is disabled due to unexpected exception:</h1>
<br>
<pre>{{ exception.toString() }}</pre>
<br>
<h1>Stack trace:</h1>
<br>
<pre>{{ stackTrace.toString() }}</pre>
</div>
</div>
</template>
<template if="{{ state == 'kLoaded' }}">
<div class="memberList">
<div class="memberItem">
<div class="memberName">Refreshed at </div>
<div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime }}) (loaded in {{ loadTime }})</div>
</div>
<div class="memberItem">
<div class="memberName">Profile contains</div>
<div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
</div>
<div class="memberItem">
<div class="memberName">Sampling</div>
<div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
</div>
<template if="{{ showTagSelector }}">
<div class="memberItem">
<div class="memberName">Tag Order</div>
<div class="memberValue">
<select value="{{tagSelector}}">
<option value="UserVM">User &gt; VM</option>
<option value="UserOnly">User</option>
<option value="VMUser">VM &gt; User</option>
<option value="VMOnly">VM</option>
<option value="None">None</option>
</select>
</div>
</div>
</template>
</div>
</template>
</div>
</template>
</polymer-element>
<polymer-element name="stack-trace-tree-config" extends="observatory-element">
<template>
<link rel="stylesheet" href="css/shared.css">
<style>
.statusBox {
height: 100%;
padding: 1em;
}
</style>
<div class="content-centered-big">
<template if="{{ show }}">
<h2>Tree display</h2>
<hr>
<div class="memberList">
<template if="{{ showModeSelector }}">
<div class="memberItem">
<div class="memberName">Mode</div>
<div class="memberValue">
<select value="{{modeSelector}}">
<option value="Code">Code</option>
<option value="Function">Function</option>
</select>
</div>
</div>
</template>
<template if="{{ showDirectionSelector }}">
<div class="memberItem">
<div class="memberName">Call Tree Direction</div>
<div class="memberValue">
<select value="{{directionSelector}}">
<option value="Down">Top down</option>
<option value="Up">Bottom up</option>
</select>
</div>
</div>
</template>
</div>
<template if="{{ directionSelector == 'Down' }}">
<br>
<div class="statusBox shadow">
<div>Tree is rooted at main.</div>
<br>
<div>Child nodes are callees.</div>
</div>
</template>
<template if="{{ directionSelector == 'Up' }}">
<br>
<div class="statusBox shadow">
<div>Tree is rooted at executing function / code.</div>
<br>
<div>Child nodes are callers.</div>
</div>
</template>
</template>
</div>
</template>
</polymer-element>
<polymer-element name="cpu-profile-tree" extends="observatory-element">
<template>
<link rel="stylesheet" href="css/shared.css">
<style>
.infoBox {
position: absolute;
top: 100%;
left: 0%;
z-index: 999;
opacity: 1;
padding: 1em;
background-color: #ffffff;
border-left: solid 2px #ECECEC;
border-bottom: solid 2px #ECECEC;
border-right: solid 2px #ECECEC;
}
.full-width {
width: 100%;
}
.tree {
border-spacing: 0px;
width: 100%;
margin-bottom: 20px
vertical-align: middle;
}
.tree tbody tr {
animation: fadeIn 0.5s;
-moz-animation: fadeIn 0.5s;
-webkit-animation: fadeIn 0.5s;
}
.tree tbody tr:hover {
background-color: #FAFAFA;
}
.tree tr td:first-child,
.tree tr th:first-child {
width: 100%;
}
.tree thead > tr > th {
padding: 8px;
vertical-align: bottom;
text-align: left;
border-bottom: 1px solid #ddd;
}
tr {
background-color: #FFFFFF;
}
tbody tr {
animation: fadeIn 0.5s;
-moz-animation: fadeIn 0.5s;
-webkit-animation: fadeIn 0.5s;
}
tbody tr:hover {
background-color: #FAFAFA;
}
tr td:first-child,
tr th:first-child {
width: 100%;
}
</style>
<table id="treeTable" class="full-width tree">
<thead id="treeHeader">
<tr>
<th>Method</th>
<th>Executing</th>
</tr>
</thead>
<tbody id="treeBody">
</tbody>
</table>
</template>
</polymer-element>
<polymer-element name="cpu-profile-table" extends="observatory-element">
<template>
<link rel="stylesheet" href="css/shared.css">
<nav-bar>
<top-nav-menu></top-nav-menu>
<vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
<isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
<nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
<nav-refresh callback="{{ refresh }}"></nav-refresh>
<nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
</nav-bar>
<style>
/* general */
.well {
background-color: #ECECEC;
padding: 0.2em;
}
.center {
align-items: center;
justify-content: center;
}
/* status messages */
.statusMessage {
font-size: 150%;
font-weight: bold;
}
.statusBox {
height: 100%;
padding: 1em;
}
/* tables */
.table {
border-collapse: collapse!important;
table-layout: fixed;
height: 100%;
}
.th, .td {
padding: 8px;
vertical-align: top;
}
.table thead > tr > th {
vertical-align: bottom;
text-align: left;
border-bottom:2px solid #ddd;
}
.spacer {
width: 16px;
}
.left-border-spacer {
width: 16px;
border-left: 1px solid;
}
.clickable {
color: #0489c3;
text-decoration: none;
cursor: pointer;
min-width: 8em;
}
.clickable:hover {
text-decoration: underline;
cursor: pointer;
}
tr:hover:not(.focused) > td {
background-color: #FAFAFA;
}
.focused {
background-color: #F4C7C3;
}
.scroll {
overflow: scroll;
}
.outlined {
-webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
margin: 4px;
}
.centered {
margin-left: auto;
margin-right: auto;
justify-content: center;
}
.full-height {
height: 100%;
}
.mostly-full-height {
height: 80%;
}
.full-width {
width: 100%;
}
.focused-function-label {
flex: 0 1 auto;
margin-left: auto;
margin-right: auto;
justify-content: center;
}
.call-table {
flex: 1 1 auto;
}
.tree {
border-spacing: 0px;
width: 100%;
margin-bottom: 20px
vertical-align: middle;
}
.tree tbody tr {
animation: fadeIn 0.5s;
-moz-animation: fadeIn 0.5s;
-webkit-animation: fadeIn 0.5s;
}
.tree tbody tr:hover {
background-color: #FAFAFA;
}
.tree tr td:first-child,
.tree tr th:first-child {
width: 100%;
}
.tree thead > tr > th {
padding: 8px;
vertical-align: bottom;
text-align: left;
border-bottom: 1px solid #ddd;
}
</style>
<sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
<br>
<hr>
<div id="main" class="flex-row centered">
<div class="flex-item-45-percent full-height outlined scroll">
<table id="main-table" class="flex-item-100-percent table">
<thead>
<tr>
<th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
<th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
<th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
</tr>
</thead>
<tbody id="profile-table">
</tbody>
</table>
</div>
<div class="flex-item-45-percent full-height outlined">
<div class="flex-column full-height">
<div class="focused-function-label">
<template if="{{ focusedFunction != null }}">
<span>Focused on: </span>
<function-ref ref="{{ focusedFunction }}"></function-ref>
</template>
<template if="{{ focusedFunction == null }}">
<span>No focused function</span>
</template>
</div>
<hr>
<div class="call-table scroll">
<table class="full-width table">
<thead>
<tr>
<th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
<th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
</tr>
</thead>
<tbody id="callers-table">
</tbody>
</table>
</div>
<hr>
<div class="call-table scroll">
<table class="full-width table">
<thead>
<tr>
<th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
<th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
</tr>
</thead>
<tbody id="callees-table">
</tbody>
</table>
</div>
</div>
</div>
</div>
<br>
<stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
<br>
<div class="content-centered-big">
<div class="focused-function-label">
<template if="{{ focusedFunction != null }}">
<span>Filtered tree: </span>
<function-ref ref="{{ focusedFunction }}"></function-ref>
</template>
<template if="{{ focusedFunction == null }}">
<span>No focused function</span>
</template>
</div>
</div>
<br>
<br>
<div class="flex-row centered">
<div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
<cpu-profile-tree id="cpuProfileTree"></cpu-profile-tree>
</div>
</div>
</template>
</polymer-element>
<polymer-element name="cpu-profile" extends="observatory-element">
<template>
<link rel="stylesheet" href="css/shared.css">
<nav-bar>
<top-nav-menu></top-nav-menu>
<vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
<isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
<nav-menu link="{{ makeLink('/profiler', isolate) }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
<nav-refresh callback="{{ refresh }}"></nav-refresh>
<nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
</nav-bar>
<style>
.tableWell {
background-color: #ECECEC;
padding: 0.2em;
}
</style>
<sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
<br>
<stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
<br>
<div class="content-centered-big">
<div class="tableWell shadow">
<cpu-profile-tree id="cpuProfileTree"></cpu-profile-tree>
</div>
</div>
<view-footer></view-footer>
</template>
</polymer-element>
<script type="application/dart" src="cpu_profile.dart"></script>