| <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 > VM</option> |
| <option value="UserOnly">User</option> |
| <option value="VMUser">VM > 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> |