| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library heap_map_element; | 5 library heap_map_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'dart:math'; | 9 import 'dart:math'; |
| 10 import 'observatory_element.dart'; | 10 import 'observatory_element.dart'; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 var _fragmentationCanvas; | 54 var _fragmentationCanvas; |
| 55 var _fragmentationData; | 55 var _fragmentationData; |
| 56 var _pageHeight; | 56 var _pageHeight; |
| 57 var _classIdToColor = {}; | 57 var _classIdToColor = {}; |
| 58 var _colorToClassId = {}; | 58 var _colorToClassId = {}; |
| 59 var _classIdToName = {}; | 59 var _classIdToName = {}; |
| 60 | 60 |
| 61 static final _freeColor = [255, 255, 255, 255]; | 61 static final _freeColor = [255, 255, 255, 255]; |
| 62 static final _pageSeparationColor = [0, 0, 0, 255]; | 62 static final _pageSeparationColor = [0, 0, 0, 255]; |
| 63 static const _PAGE_SEPARATION_HEIGHT = 4; | 63 static const _PAGE_SEPARATION_HEIGHT = 4; |
| 64 // Many browsers will not display a very tall canvas. |
| 65 // TODO(koda): Improve interface for huge heaps. |
| 66 static const _MAX_CANVAS_HEIGHT = 6000; |
| 64 | 67 |
| 65 @observable String status; | 68 @observable String status; |
| 66 @published ServiceMap fragmentation; | 69 @published ServiceMap fragmentation; |
| 67 | 70 |
| 68 HeapMapElement.created() : super.created() { | 71 HeapMapElement.created() : super.created() { |
| 69 } | 72 } |
| 70 | 73 |
| 71 void enteredView() { | 74 void enteredView() { |
| 72 super.enteredView(); | 75 super.enteredView(); |
| 73 _fragmentationCanvas = shadowRoot.querySelector("#fragmentation"); | 76 _fragmentationCanvas = shadowRoot.querySelector("#fragmentation"); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 if (fragmentation == null || _fragmentationCanvas == null) { | 161 if (fragmentation == null || _fragmentationCanvas == null) { |
| 159 return; | 162 return; |
| 160 } | 163 } |
| 161 _updateClassList( | 164 _updateClassList( |
| 162 fragmentation['class_list'], fragmentation['free_class_id']); | 165 fragmentation['class_list'], fragmentation['free_class_id']); |
| 163 var pages = fragmentation['pages']; | 166 var pages = fragmentation['pages']; |
| 164 var width = _fragmentationCanvas.parent.client.width; | 167 var width = _fragmentationCanvas.parent.client.width; |
| 165 _pageHeight = _PAGE_SEPARATION_HEIGHT + | 168 _pageHeight = _PAGE_SEPARATION_HEIGHT + |
| 166 fragmentation['page_size_bytes'] ~/ | 169 fragmentation['page_size_bytes'] ~/ |
| 167 fragmentation['unit_size_bytes'] ~/ width; | 170 fragmentation['unit_size_bytes'] ~/ width; |
| 168 var height = _pageHeight * pages.length; | 171 var height = min(_pageHeight * pages.length, _MAX_CANVAS_HEIGHT); |
| 169 _fragmentationData = | 172 _fragmentationData = |
| 170 _fragmentationCanvas.context2D.createImageData(width, height); | 173 _fragmentationCanvas.context2D.createImageData(width, height); |
| 171 _fragmentationCanvas.width = _fragmentationData.width; | 174 _fragmentationCanvas.width = _fragmentationData.width; |
| 172 _fragmentationCanvas.height = _fragmentationData.height; | 175 _fragmentationCanvas.height = _fragmentationData.height; |
| 173 _renderPages(0); | 176 _renderPages(0); |
| 174 } | 177 } |
| 175 | 178 |
| 176 // Renders and draws asynchronously, one page at a time to avoid | 179 // Renders and draws asynchronously, one page at a time to avoid |
| 177 // blocking the UI. | 180 // blocking the UI. |
| 178 void _renderPages(int startPage) { | 181 void _renderPages(int startPage) { |
| 179 var pages = fragmentation['pages']; | 182 var pages = fragmentation['pages']; |
| 180 status = 'Loaded $startPage of ${pages.length} pages'; | 183 status = 'Loaded $startPage of ${pages.length} pages'; |
| 181 if (startPage >= pages.length) { | 184 var startY = startPage * _pageHeight; |
| 185 var endY = startY + _pageHeight; |
| 186 if (startPage >= pages.length || endY > _fragmentationData.height) { |
| 182 return; | 187 return; |
| 183 } | 188 } |
| 184 var startY = startPage * _pageHeight; | |
| 185 var pixel = new PixelReference(_fragmentationData, new Point(0, startY)); | 189 var pixel = new PixelReference(_fragmentationData, new Point(0, startY)); |
| 186 var objects = pages[startPage]['objects']; | 190 var objects = pages[startPage]['objects']; |
| 187 for (var i = 0; i < objects.length; i += 2) { | 191 for (var i = 0; i < objects.length; i += 2) { |
| 188 var count = objects[i]; | 192 var count = objects[i]; |
| 189 var classId = objects[i + 1]; | 193 var classId = objects[i + 1]; |
| 190 var color = _classIdToColor[classId]; | 194 var color = _classIdToColor[classId]; |
| 191 while (count-- > 0) { | 195 while (count-- > 0) { |
| 192 pixel.color = color; | 196 pixel.color = color; |
| 193 pixel = pixel.next(); | 197 pixel = pixel.next(); |
| 194 } | 198 } |
| 195 } | 199 } |
| 196 var endY = startY + _pageHeight; | |
| 197 while (pixel.point.y < endY) { | 200 while (pixel.point.y < endY) { |
| 198 pixel.color = _pageSeparationColor; | 201 pixel.color = _pageSeparationColor; |
| 199 pixel = pixel.next(); | 202 pixel = pixel.next(); |
| 200 } | 203 } |
| 201 _fragmentationCanvas.context2D.putImageData( | 204 _fragmentationCanvas.context2D.putImageData( |
| 202 _fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY); | 205 _fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY); |
| 203 // Continue with the next page, asynchronously. | 206 // Continue with the next page, asynchronously. |
| 204 new Future(() { | 207 new Future(() { |
| 205 _renderPages(startPage + 1); | 208 _renderPages(startPage + 1); |
| 206 }); | 209 }); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 218 }).whenComplete(done); | 221 }).whenComplete(done); |
| 219 } | 222 } |
| 220 | 223 |
| 221 void fragmentationChanged(oldValue) { | 224 void fragmentationChanged(oldValue) { |
| 222 // Async, in case enteredView has not yet run (observed in JS version). | 225 // Async, in case enteredView has not yet run (observed in JS version). |
| 223 new Future(() { | 226 new Future(() { |
| 224 _updateFragmentationData(); | 227 _updateFragmentationData(); |
| 225 }); | 228 }); |
| 226 } | 229 } |
| 227 } | 230 } |
| OLD | NEW |