Friday, January 13, 2012

Heavy vs. Light Dart Isolates

‹prev | My Chain | next›

Spurred by some comments in a previous post, I investigate the differences between light and heavy Isolates in Dart. Heavy isolates run in separate threads whereas the light versions all run in the same thread. In theory this should mean that heavy threads can take better advantage of multi-core CPUs. Let's see if "in-practice" agrees.

For my testing, I am using the following for heavy Isolates:
#import('pretty_stopwatch.dart');
#import('solver_heavy.dart');
#source('spawn.dart');

main() {
  final fib_solver = new FibSolver();

  // List of number to obtain the fibonacci number
  var list = [5, 40, 39, 32, 6, 41];

  // Timer
  var timer = new PrettyStopwatch.start()
    , completer = new Completer();

  // completer to be signaled when all isolates complete
  completer.future.then((args) {
    timer.stop();
  });

  // spawn 2 isolates, each solving half
  spawn(fib_solver, list, completer);
}
The only difference between this version and the light version is the solver being imported. And the only difference between the two solver libraries is the constructor being used:
#library('heavy weight isolates for solving fibs');

class FibSolver extends Isolate {
  FibSolver(): super.heavy();
  // ...
}
When I run the heavy version from the command line, I find:
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6406ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6648ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6540ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 7631ms
So, around 6.5 seconds.

When I do the same for the lighter version, I find:
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6880ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6328ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6418ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 7480ms
Again, around 6.5 seconds. So unexpectedly, there is no difference.

Perhaps this is not yet implemented in the command line tool? To test that hypothesis, I load the same script up in the browser. For the heavy version, I find:
(try on dart4hipsters -- requires Dart-enabled browser)

For the light version, I find:

(try on dart4hipsters -- requires Dart-enabled browser)

So again, both are about the same.

For completeness, I do the same for compiled Javascript versions. But, since Javascript is single-threaded, there should certainly be no differences.

For the heavy version I find that the numbers are a little slower than the Dart equivalent:

(try on dart4hipsters)

But, astonishingly, the light version is much, much slower:
(try on dart4hipsters)

I reload the web page several times to be sure that the results are consistent. Within an acceptable margin, the light Javascript Isolates are always nearly twice as slow as the heavy version.

I am quite surprised by this. Since Dart can be multi-threaded, while Javascript is always single threaded, I would have expected to find discrepancies between heavy and light isolates in Dart, not Javascript. I can only speculate as to why at this point, but I would guess that light-weight Isolates are not yet implemented in Dart (I can see two CPUs pegged for both scenarios). As for the Javascript differences, I know that Chrome is capable of doing some calculations multi-threaded even though Javascript is normally single threaded. I can only guess that Chrome is doing so for the heavy.js case.

I will investigate a bit more tomorrow.


Day #264

No comments:

Post a Comment