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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart

Issue 2811343002: Dev compiler debugger related tweaks. (Closed)
Patch Set: Created 3 years, 8 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) 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 /// This library defines runtime operations on objects used by the code 5 /// This library defines runtime operations on objects used by the code
6 /// generator. 6 /// generator.
7 part of dart._runtime; 7 part of dart._runtime;
8 8
9 class InvocationImpl extends Invocation { 9 class InvocationImpl extends Invocation {
10 final Symbol memberName; 10 final Symbol memberName;
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 (resolvedField) => _callMethod(obj, resolvedField, typeArgs, args, method)); 357 (resolvedField) => _callMethod(obj, resolvedField, typeArgs, args, method));
358 358
359 dsendRepl(obj, method, @rest args) => _callMethodRepl(obj, method, null, args); 359 dsendRepl(obj, method, @rest args) => _callMethodRepl(obj, method, null, args);
360 360
361 dgsendRepl(obj, typeArgs, method, @rest args) => 361 dgsendRepl(obj, typeArgs, method, @rest args) =>
362 _callMethodRepl(obj, method, typeArgs, args); 362 _callMethodRepl(obj, method, typeArgs, args);
363 363
364 class _MethodStats { 364 class _MethodStats {
365 final String typeName; 365 final String typeName;
366 final String frame; 366 final String frame;
367 int count; 367 double count;
368 368
369 _MethodStats(this.typeName, this.frame) { 369 _MethodStats(this.typeName, this.frame) {
370 count = 0; 370 count = 0.0;
371 } 371 }
372 } 372 }
373 373
374 class _CallMethodRecord {
375 var jsError;
376 var type;
377
378 _CallMethodRecord(this.jsError, this.type);
379 }
380
374 Map<String, _MethodStats> _callMethodStats = new Map(); 381 Map<String, _MethodStats> _callMethodStats = new Map();
375 382
383 // Randomly sampled list of call records
384 List<_CallMethodRecord> _callMethodRecords = new List();
385 int totalCallRecords = 0;
386 int _callRecordSampleSize = 5000;
387 num _minCount = 0;
388
389 /// Mapping from raw stack frames to source mapped stack frames to speedup
390 /// lookup of source map frames.
391 Map<String, String> _frameMappingCache = new Map();
392
376 List<List<Object>> getDynamicStats() { 393 List<List<Object>> getDynamicStats() {
377 List<List<Object>> ret = []; 394 List<List<Object>> ret = [];
395 // Process the accumulated method stats. This may be quite slow as processing
396 // stack traces is expensive. If there are performance blockers, we should
397 // switch to a sampling approach that caps the number of _callMethodRecords
398 // and uses random sampling to decide whether to add each additional record
399 // to the sample. Main change required is that we need to still show the total
400 // raw number of dynamic calls so that the magnitude of the dynamic call
401 // performance hit is clear to users.
378 402
403 // Minimum number of samples to consider a profile entry relevant.
404 // This could be set a lot higher. We set this value so users are not
405 // confused into thinking that a dynamic call that occurred once but was
406 // randomly included in the sample is relevant.
407 if (_callMethodRecords.length > 0) {
408 // Ratio between total record count and sampled records count.
409 var recordRatio = totalCallRecords / _callMethodRecords.length;
410 _minCount = recordRatio * 1.99;
411 for (var record in _callMethodRecords) {
412 var stackStr = JS('String', '#.stack', record.jsError);
413 // Truncate the stacktrace as we are only interested in the top 3-4 frames .
414 var frames = stackStr.split('\n');
415 var src = '';
416 for (int i = 2; i < frames.length; ++i) {
417 var frame = frames[i];
418 var mappedFrame = _frameMappingCache.putIfAbsent(frame, () {
419 return stackTraceMapper('\n${frame}');
420 });
421 if (!mappedFrame.contains(
422 'dart:_internal/js_runtime/lib/ddc_runtime/operations.dart')) {
423 src = mappedFrame;
424 break;
425 }
426 }
427
428 var actualTypeName = typeName(record.type);
429 _callMethodStats
430 .putIfAbsent("$actualTypeName <$src>",
431 () => new _MethodStats(actualTypeName, src))
432 .count += recordRatio;
433 }
434 }
435 // filter out
436 _callMethodRecords.clear();
437 totalCallRecords = 0;
379 var keys = _callMethodStats.keys.toList(); 438 var keys = _callMethodStats.keys.toList();
380 439
381 keys.sort( 440 keys.sort(
382 (a, b) => _callMethodStats[b].count.compareTo(_callMethodStats[a].count)); 441 (a, b) => _callMethodStats[b].count.compareTo(_callMethodStats[a].count));
383 for (var key in keys) { 442 for (var key in keys) {
384 var stats = _callMethodStats[key]; 443 var stats = _callMethodStats[key];
385 ret.add([stats.typeName, stats.frame, stats.count]); 444 if (_minCount < stats.count) {
445 ret.add([stats.typeName, stats.frame, stats.count.round()]);
446 }
386 } 447 }
387 448
388 return ret; 449 return ret;
389 } 450 }
390 451
391 clearDynamicStats() { 452 clearDynamicStats() {
392 _callMethodStats.clear(); 453 _callMethodStats.clear();
454 _callMethodRecords.clear();
393 } 455 }
394 456
395 bool trackProfile = JS('bool', 'dart.global.trackDdcProfile'); 457 bool trackProfile = JS('bool', 'dart.global.trackDdcProfile');
396 458
397 _trackCall(obj) { 459 _trackCall(obj) {
398 if (JS('bool', '!#', trackProfile)) return; 460 if (JS('bool', '!#', trackProfile)) return;
399 461 int index = -1;
400 var actual = getReifiedType(obj); 462 totalCallRecords++;
401 String stackStr = JS('String', "new Error().stack"); 463 if (_callMethodRecords.length == _callRecordSampleSize) {
402 var stack = stackStr.split('\n at '); 464 // Unfortunately we can't use the excellent Random.nextInt method defined
403 var src = ''; 465 // by Dart from within this library.
404 for (int i = 2; i < stack.length; ++i) { 466 index = JS('int', 'Math.floor(Math.random() * #)', totalCallRecords);
405 var frame = stack[i]; 467 if (index >= _callMethodRecords.length) return; // don't sample
406 if (!frame.contains('dart_sdk.js')) {
407 src = frame;
408 break;
409 }
410 } 468 }
411 469 var record =
412 var actualTypeName = typeName(actual); 470 new _CallMethodRecord(JS('', 'new Error()'), getReifiedType(obj));
413 _callMethodStats 471 if (index == -1) {
414 .putIfAbsent( 472 _callMethodRecords.add(record);
415 "$actualTypeName <$src>", () => new _MethodStats(actualTypeName, src)) 473 } else {
416 .count++; 474 _callMethodRecords[index] = record;
475 }
417 } 476 }
418 477
419 /// Shared code for dsend, dindex, and dsetindex. 478 /// Shared code for dsend, dindex, and dsetindex.
420 _callMethod(obj, name, typeArgs, args, displayName) { 479 _callMethod(obj, name, typeArgs, args, displayName) {
421 var symbol = _canonicalMember(obj, name); 480 var symbol = _canonicalMember(obj, name);
422 if (symbol == null) { 481 if (symbol == null) {
423 return noSuchMethod( 482 return noSuchMethod(
424 obj, new InvocationImpl(displayName, args, isMethod: true)); 483 obj, new InvocationImpl(displayName, args, isMethod: true));
425 } 484 }
426 var f = obj != null ? JS('', '#[#]', obj, symbol) : null; 485 var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 name = '+' + name; 1042 name = '+' + name;
984 } 1043 }
985 return name; 1044 return name;
986 } 1045 }
987 1046
988 /// Emulates the implicit "loadLibrary" function provided by a deferred library. 1047 /// Emulates the implicit "loadLibrary" function provided by a deferred library.
989 /// 1048 ///
990 /// Libraries are not actually deferred in DDC, so this just returns a future 1049 /// Libraries are not actually deferred in DDC, so this just returns a future
991 /// that completes immediately. 1050 /// that completes immediately.
992 Future loadLibrary() => new Future.value(); 1051 Future loadLibrary() => new Future.value();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698