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

Side by Side Diff: runtime/observatory/lib/object_graph.dart

Issue 3008593002: Add external sizes to the heap dominator tree. (Closed)
Patch Set: . Created 3 years, 3 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
OLDNEW
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 object_graph; 5 library object_graph;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:typed_data'; 9 import 'dart:typed_data';
10 10
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 bool get isRoot => ROOT == _id; 231 bool get isRoot => ROOT == _id;
232 bool get isStack => vmCid == _graph._kStackCid; 232 bool get isStack => vmCid == _graph._kStackCid;
233 233
234 bool operator ==(other) => _id == other._id && _graph == other._graph; 234 bool operator ==(other) => _id == other._id && _graph == other._graph;
235 int get hashCode => _id; 235 int get hashCode => _id;
236 236
237 int get retainedSize => _graph._retainedSizes[_id]; 237 int get retainedSize => _graph._retainedSizes[_id];
238 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); 238 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph);
239 239
240 int get shallowSize => _graph._shallowSizes[_id]; 240 int get shallowSize => _graph._shallowSizes[_id];
241 int get externalSize => _graph._externalSizes[_id];
241 int get vmCid => _graph._cids[_id]; 242 int get vmCid => _graph._cids[_id];
242 243
243 get successors => new _SuccessorsIterable(_graph, _id); 244 get successors => new _SuccessorsIterable(_graph, _id);
244 245
245 String get address { 246 String get address {
246 // Note that everywhere else in this file, "address" really means an address 247 // Note that everywhere else in this file, "address" really means an address
247 // scaled down by kObjectAlignment. They were scaled down so they would fit 248 // scaled down by kObjectAlignment. They were scaled down so they would fit
248 // into Smis on the client. 249 // into Smis on the client.
249 250
250 var high32 = _graph._addressesHigh[_id]; 251 var high32 = _graph._addressesHigh[_id];
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 var cids = _graph._cids; 315 var cids = _graph._cids;
315 var size = 0; 316 var size = 0;
316 var sibling = _id; 317 var sibling = _id;
317 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { 318 while (sibling != SENTINEL && cids[sibling] == cids[_id]) {
318 size += _graph._shallowSizes[sibling]; 319 size += _graph._shallowSizes[sibling];
319 sibling = _graph._mergedDomNext[sibling]; 320 sibling = _graph._mergedDomNext[sibling];
320 } 321 }
321 return size; 322 return size;
322 } 323 }
323 324
325 int get externalSize {
326 var cids = _graph._cids;
327 var size = 0;
328 var sibling = _id;
329 while (sibling != SENTINEL && cids[sibling] == cids[_id]) {
330 size += _graph._externalSizes[sibling];
331 sibling = _graph._mergedDomNext[sibling];
332 }
333 return size;
334 }
335
324 int get retainedSize { 336 int get retainedSize {
325 var cids = _graph._cids; 337 var cids = _graph._cids;
326 var size = 0; 338 var size = 0;
327 var sibling = _id; 339 var sibling = _id;
328 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { 340 while (sibling != SENTINEL && cids[sibling] == cids[_id]) {
329 size += _graph._retainedSizes[sibling]; 341 size += _graph._retainedSizes[sibling];
330 sibling = _graph._mergedDomNext[sibling]; 342 sibling = _graph._mergedDomNext[sibling];
331 } 343 }
332 return size; 344 return size;
333 } 345 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 current = new ObjectVertex._(_nextId++, _graph); 428 current = new ObjectVertex._(_nextId++, _graph);
417 return true; 429 return true;
418 } 430 }
419 } 431 }
420 432
421 class ObjectGraph { 433 class ObjectGraph {
422 ObjectGraph(List<ByteData> chunks, int nodeCount) 434 ObjectGraph(List<ByteData> chunks, int nodeCount)
423 : this._chunks = chunks, 435 : this._chunks = chunks,
424 this._N = nodeCount; 436 this._N = nodeCount;
425 437
426 int get size => _size; 438 int get internalSize => _internalSize;
439 int get externalSize => _externalSize;
427 int get vertexCount => _N; 440 int get vertexCount => _N;
428 int get edgeCount => _E; 441 int get edgeCount => _E;
429 442
430 ObjectVertex get root => new ObjectVertex._(ROOT, this); 443 ObjectVertex get root => new ObjectVertex._(ROOT, this);
431 MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this); 444 MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this);
432 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this); 445 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this);
433 446
434 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) { 447 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) {
435 List<ObjectVertex> _mostRetained = 448 List<ObjectVertex> _mostRetained =
436 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot)); 449 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 return controller.stream; 509 return controller.stream;
497 } 510 }
498 511
499 List<ByteData> _chunks; 512 List<ByteData> _chunks;
500 513
501 int _kObjectAlignment; 514 int _kObjectAlignment;
502 int _kStackCid; 515 int _kStackCid;
503 int _N; // Objects in the snapshot. 516 int _N; // Objects in the snapshot.
504 int _Nconnected; // Objects reachable from root. 517 int _Nconnected; // Objects reachable from root.
505 int _E; // References in the snapshot. 518 int _E; // References in the snapshot.
506 int _size; 519 int _internalSize;
520 int _externalSize;
507 521
508 // Indexed by node id, with id 0 representing invalid/uninitialized. 522 // Indexed by node id, with id 0 representing invalid/uninitialized.
509 // From snapshot. 523 // From snapshot.
510 Uint16List _cids; 524 Uint16List _cids;
511 Uint32List _shallowSizes; 525 Uint32List _shallowSizes;
526 Uint32List _externalSizes;
512 Uint32List _firstSuccs; 527 Uint32List _firstSuccs;
513 Uint32List _succs; 528 Uint32List _succs;
514 Uint32List _addressesLow; // No Uint64List in Javascript. 529 Uint32List _addressesLow; // No Uint64List in Javascript.
515 Uint32List _addressesHigh; 530 Uint32List _addressesHigh;
516 531
517 // Intermediates. 532 // Intermediates.
518 AddressMapper _addrToId; 533 AddressMapper _addrToId;
519 Uint32List _vertex; 534 Uint32List _vertex;
520 Uint32List _parent; 535 Uint32List _parent;
521 Uint32List _semi; 536 Uint32List _semi;
522 Uint32List _firstPreds; // Offset into preds. 537 Uint32List _firstPreds; // Offset into preds.
523 Uint32List _preds; 538 Uint32List _preds;
524 539
525 // Outputs. 540 // Outputs.
526 Uint32List _doms; 541 Uint32List _doms;
527 Uint32List _retainedSizes; 542 Uint32List _retainedSizes;
528 Uint32List _mergedDomHead; 543 Uint32List _mergedDomHead;
529 Uint32List _mergedDomNext; 544 Uint32List _mergedDomNext;
530 545
531 void _remapNodes() { 546 void _remapNodes() {
532 var N = _N; 547 var N = _N;
533 var E = 0; 548 var E = 0;
534 var addrToId = new AddressMapper(N); 549 var addrToId = new AddressMapper(N);
535 550
536 var addressesHigh = new Uint32List(N + 1); 551 var addressesHigh = new Uint32List(N + 1);
537 var addressesLow = new Uint32List(N + 1); 552 var addressesLow = new Uint32List(N + 1);
538 var shallowSizes = new Uint32List(N + 1); 553 var shallowSizes = new Uint32List(N + 1);
554 var externalSizes = new Uint32List(N + 1);
539 var cids = new Uint16List(N + 1); 555 var cids = new Uint16List(N + 1);
540 556
541 var stream = new ReadStream(_chunks); 557 var stream = new ReadStream(_chunks);
542 stream.readUnsigned(); 558 stream.readUnsigned();
543 _kObjectAlignment = stream.clampedUint32; 559 _kObjectAlignment = stream.clampedUint32;
544 stream.readUnsigned(); 560 stream.readUnsigned();
545 _kStackCid = stream.clampedUint32; 561 _kStackCid = stream.clampedUint32;
546 562
547 var id = ROOT; 563 var id = ROOT;
548 while (stream.pendingBytes > 0) { 564 while (id <= N) {
549 stream.readUnsigned(); // addr 565 stream.readUnsigned(); // addr
550 addrToId.put(stream.high, stream.mid, stream.low, id); 566 addrToId.put(stream.high, stream.mid, stream.low, id);
551 addressesHigh[id] = stream.highUint32; 567 addressesHigh[id] = stream.highUint32;
552 addressesLow[id] = stream.lowUint32; 568 addressesLow[id] = stream.lowUint32;
553 stream.readUnsigned(); // shallowSize 569 stream.readUnsigned(); // shallowSize
554 shallowSizes[id] = stream.clampedUint32; 570 shallowSizes[id] = stream.clampedUint32;
555 stream.readUnsigned(); // cid 571 stream.readUnsigned(); // cid
556 cids[id] = stream.clampedUint32; 572 cids[id] = stream.clampedUint32;
557 573
558 stream.readUnsigned(); 574 stream.readUnsigned();
559 while (!stream.isZero) { 575 while (!stream.isZero) {
560 E++; 576 E++;
561 stream.readUnsigned(); 577 stream.readUnsigned();
562 } 578 }
563 id++; 579 id++;
564 } 580 }
565 assert(id == (N + 1)); 581 assert(id == (N + 1));
cbernaschina 2017/08/28 16:15:18 Is this assertion still needed?
rmacnak 2017/08/28 17:08:20 No, this isn't useful anymore. Removed.
566 582
567 assert(ROOT == addrToId.get(0, 0, 0)); 583 assert(ROOT == addrToId.get(0, 0, 0));
568 584
585 stream.readUnsigned();
586 assert(stream.isZero);
587
588 stream.readUnsigned(); // addr
589 while (!stream.isZero) {
590 var nodeId = addrToId.get(stream.high, stream.mid, stream.low);
591 stream.readUnsigned(); // externalSize
592 externalSizes[nodeId] += stream.clampedUint32;
593
594 stream.readUnsigned(); // addr
595 }
596
569 _E = E; 597 _E = E;
570 _addrToId = addrToId; 598 _addrToId = addrToId;
571 _addressesLow = addressesLow; 599 _addressesLow = addressesLow;
572 _addressesHigh = addressesHigh; 600 _addressesHigh = addressesHigh;
573 _shallowSizes = shallowSizes; 601 _shallowSizes = shallowSizes;
602 _externalSizes = externalSizes;
574 _cids = cids; 603 _cids = cids;
575 } 604 }
576 605
577 void _remapEdges() { 606 void _remapEdges() {
578 var N = _N; 607 var N = _N;
579 var E = _E; 608 var E = _E;
580 var addrToId = _addrToId; 609 var addrToId = _addrToId;
581 610
582 var firstSuccs = new Uint32List(N + 2); 611 var firstSuccs = new Uint32List(N + 2);
583 var succs = new Uint32List(E); 612 var succs = new Uint32List(E);
584 613
585 var stream = new ReadStream(_chunks); 614 var stream = new ReadStream(_chunks);
586 stream.skipUnsigned(); // kObjectAlignment 615 stream.skipUnsigned(); // kObjectAlignment
587 stream.skipUnsigned(); // kStackCid 616 stream.skipUnsigned(); // kStackCid
588 617
589 var id = 1, edge = 0; 618 var id = 1, edge = 0;
590 while (stream.pendingBytes > 0) { 619 while (id <= N) {
591 stream.skipUnsigned(); // addr 620 stream.skipUnsigned(); // addr
592 stream.skipUnsigned(); // shallowSize 621 stream.skipUnsigned(); // shallowSize
593 stream.skipUnsigned(); // cid 622 stream.skipUnsigned(); // cid
594 623
595 firstSuccs[id] = edge; 624 firstSuccs[id] = edge;
596 625
597 stream.readUnsigned(); 626 stream.readUnsigned();
598 while (!stream.isZero) { 627 while (!stream.isZero) {
599 var childId = addrToId.get(stream.high, stream.mid, stream.low); 628 var childId = addrToId.get(stream.high, stream.mid, stream.low);
600 if (childId != null) { 629 if (childId != null) {
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 var w = vertex[i]; 937 var w = vertex[i];
909 if (dom[w] != vertex[semi[w]]) { 938 if (dom[w] != vertex[semi[w]]) {
910 dom[w] = dom[dom[w]]; 939 dom[w] = dom[dom[w]];
911 } 940 }
912 } 941 }
913 942
914 _doms = dom; 943 _doms = dom;
915 } 944 }
916 945
917 void _calculateRetainedSizes() { 946 void _calculateRetainedSizes() {
947 var N = _N;
918 var Nconnected = _Nconnected; 948 var Nconnected = _Nconnected;
919 949
920 var size = 0; 950 var internalSize = 0;
951 var externalSize = 0;
921 var shallowSizes = _shallowSizes; 952 var shallowSizes = _shallowSizes;
953 var externalSizes = _externalSizes;
922 var vertex = _vertex; 954 var vertex = _vertex;
923 var doms = _doms; 955 var doms = _doms;
924 956
925 // Sum shallow sizes. 957 // Sum internal and external sizes.
926 for (var i = 1; i <= Nconnected; i++) { 958 for (var i = 1; i <= Nconnected; i++) {
927 var v = vertex[i]; 959 var v = vertex[i];
928 size += shallowSizes[v]; 960 internalSize += shallowSizes[v];
961 externalSize += externalSizes[v];
929 } 962 }
930 963
931 // Start with retained size as shallow size. 964 // Start with retained size as shallow size + external size.
932 var retainedSizes = new Uint32List.fromList(shallowSizes); 965 var retainedSizes = new Uint32List(N + 1);
966 for (var i = 0; i < N + 1; i++) {
967 retainedSizes[i] = shallowSizes[i] + externalSizes[i];
968 }
933 969
934 // In post order (bottom up), add retained size to dominator's retained 970 // In post order (bottom up), add retained size to dominator's retained
935 // size, skipping root. 971 // size, skipping root.
936 for (var i = Nconnected; i > 1; i--) { 972 for (var i = Nconnected; i > 1; i--) {
937 var v = vertex[i]; 973 var v = vertex[i];
938 assert(v != ROOT); 974 assert(v != ROOT);
939 retainedSizes[doms[v]] += retainedSizes[v]; 975 retainedSizes[doms[v]] += retainedSizes[v];
940 } 976 }
941 977
942 assert(retainedSizes[ROOT] == size); // Root retains everything. 978 // Root retains everything.
979 assert(retainedSizes[ROOT] == (internalSize + externalSize));
943 980
944 _retainedSizes = retainedSizes; 981 _retainedSizes = retainedSizes;
945 _size = size; 982 _internalSize = internalSize;
983 _externalSize = externalSize;
946 } 984 }
947 985
948 // Build linked lists of the children for each node in the dominator tree. 986 // Build linked lists of the children for each node in the dominator tree.
949 void _linkDominatorChildren() { 987 void _linkDominatorChildren() {
950 var N = _N; 988 var N = _N;
951 var doms = _doms; 989 var doms = _doms;
952 var head = new Uint32List(N + 1); 990 var head = new Uint32List(N + 1);
953 var next = new Uint32List(N + 1); 991 var next = new Uint32List(N + 1);
954 992
955 for (var child = ROOT; child <= N; child++) { 993 for (var child = ROOT; child <= N; child++) {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 1132
1095 // From all the siblings between child and after, take their children, 1133 // From all the siblings between child and after, take their children,
1096 // merge them and given to child. 1134 // merge them and given to child.
1097 mergeChildrenAndSort(child, after); 1135 mergeChildrenAndSort(child, after);
1098 1136
1099 child = after; 1137 child = after;
1100 } 1138 }
1101 } 1139 }
1102 } 1140 }
1103 } 1141 }
OLDNEW
« no previous file with comments | « no previous file | runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart » ('j') | runtime/observatory/pubspec.yaml » ('J')

Powered by Google App Engine
This is Rietveld 408576698