angular/angular.dart — pull request #353 by kasperl (2013-12-16 12:25:39+00:00)
Title: perf(digest): Split the digest loop into smaller and faster functions

The Dart VM and the JS engines tend to have an easier time optimizing smaller functions, so this is an attempt to split the functionality of the digest loop into simpler functions. The first run through the watch expressions is separated out and optimized for not finding any dirty watchers.

_Note_: This proposed change has an impact on how we deal with exceptions thrown as part of evaluating watch expressions. Before this change, we would continue evaluating the next expression, but now we abandon the entire digest loop on the first exception. According to James deBoer, this should be fine. We may want to consider changing the async queue handling to do the same.

## Performance
The performance of the digest loop (as measured by perf/scope_perf.dart) gets a nice improvement on both the native Dart VM and when translated to JavaScript.

### Old code: Dart VM
noop: => 192,729,266 ops/sec (0 us) stdev(0.85125)
empty scope $digest(): => 4,149,363 ops/sec (0 us) stdev(0.06924)
adding/removing 4000 watchers: => 188 ops/sec (5,312 us) stdev(0)
4000 dummy watchers on scope: => 3,280 ops/sec (305 us) stdev(0.00002)
3000 watchers on scope: => 161 ops/sec (6,226 us) stdev(0.00001)

### New code: Dart VM
noop: => 195,604,558 ops/sec (0 us) stdev(0.97016)
empty scope $digest(): => 11,080,508 ops/sec (0 us) stdev(0.23822)
adding/removing 4000 watchers: => 177 ops/sec (5,665 us) stdev(0)
4000 dummy watchers on scope: => 11,773 ops/sec (85 us) stdev(0.00008)
3000 watchers on scope: => 202 ops/sec (4,958 us) stdev(0.00002)

### Old code: dart2js
noop: => 152,401,333,333 ops/sec (0 us) stdev(519.23081)
empty scope $digest(): => 540,986 ops/sec (2 us) stdev(0.00791)
adding/removing 4000 watchers: => 402 ops/sec (2,489 us) stdev(0.00001)
4000 dummy watchers on scope: => 7,028 ops/sec (142 us) stdev(0.0001)
3000 watchers on scope: => 182 ops/sec (5,508 us) stdev(0.00001)

### New code: dart2js
noop: => 151,732,155,556 ops/sec (0 us) stdev(164.26959)
empty scope $digest(): => 707,211 ops/sec (1 us) stdev(0.02105)
adding/removing 4000 watchers: => 428 ops/sec (2,336 us) stdev(0)
4000 dummy watchers on scope: => 13,657 ops/sec (73 us) stdev(0.00008)
3000 watchers on scope: => 201 ops/sec (4,982 us) stdev(0.00002)