@@ -344,6 +344,59 @@ class Scope {
344
344
_mapEqual (Map a, Map b) => a.length == b.length &&
345
345
a.keys.every ((k) => b.containsKey (k) && a[k] == b[k]);
346
346
347
+ class ScopeStats {
348
+ bool report = true ;
349
+ final nf = new NumberFormat .decimalPattern ();
350
+
351
+ final digestFieldStopwatch = new AvgStopwatch ();
352
+ final digestEvalStopwatch = new AvgStopwatch ();
353
+ final digestProcessStopwatch = new AvgStopwatch ();
354
+ int _digestLoopNo = 0 ;
355
+
356
+ final flushFieldStopwatch = new AvgStopwatch ();
357
+ final flushEvalStopwatch = new AvgStopwatch ();
358
+ final flushProcessStopwatch = new AvgStopwatch ();
359
+
360
+ ScopeStats ({this .report: false }) {
361
+ nf.maximumFractionDigits = 0 ;
362
+ }
363
+
364
+ void digestStart () {
365
+ _digestStopwatchReset ();
366
+ _digestLoopNo = 0 ;
367
+ }
368
+
369
+ _digestStopwatchReset () {
370
+ digestFieldStopwatch.reset ();
371
+ digestEvalStopwatch.reset ();
372
+ digestProcessStopwatch.reset ();
373
+ }
374
+
375
+ void digestLoop (int changeCount) {
376
+ _digestLoopNo++ ;
377
+ if (report) {
378
+ print (this );
379
+ }
380
+ _digestStopwatchReset ();
381
+ }
382
+
383
+ String _stat (AvgStopwatch s) {
384
+ return '${nf .format (s .count )}'
385
+ ' / ${nf .format (s .elapsedMicroseconds )} us'
386
+ ' = ${nf .format (s .ratePerMs )} #/ms' ;
387
+ }
388
+
389
+ void digestEnd () {
390
+ }
391
+
392
+ toString () =>
393
+ 'digest #$_digestLoopNo :'
394
+ 'Field: ${_stat (digestFieldStopwatch )} '
395
+ 'Eval: ${_stat (digestEvalStopwatch )} '
396
+ 'Process: ${_stat (digestProcessStopwatch )}' ;
397
+ }
398
+
399
+
347
400
class RootScope extends Scope {
348
401
static final STATE_APPLY = 'apply' ;
349
402
static final STATE_DIGEST = 'digest' ;
@@ -360,11 +413,14 @@ class RootScope extends Scope {
360
413
_FunctionChain _domWriteHead, _domWriteTail;
361
414
_FunctionChain _domReadHead, _domReadTail;
362
415
416
+ final ScopeStats _scopeStats;
417
+
363
418
String _state;
364
419
365
420
RootScope (Object context, this ._astParser, this ._parser,
366
421
GetterCache cacheGetter, FilterMap filterMap,
367
- this ._exceptionHandler, this ._ttl, this ._zone)
422
+ this ._exceptionHandler, this ._ttl, this ._zone,
423
+ this ._scopeStats)
368
424
: super (context, null , null ,
369
425
new RootWatchGroup (new DirtyCheckingChangeDetector (cacheGetter), context),
370
426
new RootWatchGroup (new DirtyCheckingChangeDetector (cacheGetter), context))
@@ -387,6 +443,7 @@ class RootScope extends Scope {
387
443
List digestLog;
388
444
var count;
389
445
ChangeLog changeLog;
446
+ _scopeStats.digestStart ();
390
447
do {
391
448
while (_runAsyncHead != null ) {
392
449
try {
@@ -399,7 +456,11 @@ class RootScope extends Scope {
399
456
400
457
digestTTL-- ;
401
458
count = rootWatchGroup.detectChanges (
402
- exceptionHandler: _exceptionHandler, changeLog: changeLog);
459
+ exceptionHandler: _exceptionHandler,
460
+ changeLog: changeLog,
461
+ fieldStopwatch: _scopeStats.digestFieldStopwatch,
462
+ evalStopwatch: _scopeStats.digestEvalStopwatch,
463
+ processStopwatch: _scopeStats.digestProcessStopwatch);
403
464
404
465
if (digestTTL <= LOG_COUNT ) {
405
466
if (changeLog == null ) {
@@ -415,8 +476,10 @@ class RootScope extends Scope {
415
476
throw 'Model did not stabilize in ${_ttl .ttl } digests. '
416
477
'Last $LOG_COUNT iterations:\n ${log .join ('\n ' )}' ;
417
478
}
479
+ _scopeStats.digestLoop (count);
418
480
} while (count > 0 );
419
481
} finally {
482
+ _scopeStats.digestEnd ();
420
483
_transitionState (STATE_DIGEST , null );
421
484
}
422
485
}
0 commit comments