I wrote some fairly ridiculous, process heavy Dart code last night. I am pretty sure that it was actually slower than trying to do the same thing in a single process (because of bad code, not a deficiency in Dart). "Pretty sure" is the realm of coding buffoonery. As my friend and mentor Mike Barry is fond of saying, show me the numbers!
Although Dart is still quite new, it does come with a built-in timer—the
Stopwatch
class. Best of all, it is a very high precision timer, capable of measuring in CPU clock cycles or microseconds. It is also fairly easy to use:main() { final doom_finder = new DoomsDayFinder() var timer = new Stopwatch.start(); doom_finder.spawn().then((port) { port.call(2000).receive((message, replyTo) { for (var year in message) print(year); timer.stop(); }); }); print("Elapsed time: " + timer.elapsedInMs()); }The
start()
constructor allows me to instantiate and start the timer in a single line. Then, I just need to stop()
the timer when the spawned isolate/process completes—which it does when it replies to the receive()
callback.Of course, that does not work:
➜ command_line git:(master) ✗ dart timer01.dart Elapsed time: 36 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096In fact, the elapsed time that I am printing is the the number of milliseconds that the timer runs as the isolates are spawned. I need to print the timing information just after the stopwatch is stopped:
main() { final doom_finder = new DoomsDayFinder(); var timer = new Stopwatch.start(); doom_finder.spawn().then((port) { port.call(2000).receive((message, replyTo) { for (var year in message) print(year); timer.stop(); print("Elapsed time: " + timer.elapsedInMs() + "ms"); }); }); }(try.dartlang.org)
With that, I get actual timing information:
➜ command_line git:(master) ✗ dart timer01.dart 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096 Elapsed time: 2797msI am slightly put off being required to stop and print the results on two different lines. It would not be so bad if both were not buried deep in the same callback (somehow it was not quite as bad when the
print()
came afterwards). Since I have yet to really get the hang of classes in Dart, let's see if I can write one from scratch to time and print the results of things:
class PrettyStopwatch { var timer = new Stopwatch(); start() { timer.start(); } stop() { timer.stop(); print("Elapsed time: " + timer.elapsedInMs() + "ms"); } }Instead of extending the behavior of the built-in
Stopwatch
, my PrettyStopwatch
class has a stopwatch. Why not sub-class Stopwatch? Because I hate inheritance. Unless I am sure that I want inheritance, I avoid it. As written, I must instantiate and start my watch on separate lines:
main() { final doom_finder = new DoomsDayFinder(); var timer = new PrettyStopwatch(); timer.start(); doom_finder.spawn().then((port) { port.call(2000).receive((message, replyTo) { for (var year in message) print(year); timer.stop(); }); }); }I will address the separate lines in a bit. First, I have more pressing issues. Specifically, my code does not compile:
➜ command_line git:(master) ✗ dart timer02.dart '/home/cstrom/repos/dart-site/examples/command_line/timer02.dart': Error: line 57 pos 15: expression must be a compile time constant var timer = new Stopwatch(); ^Compile time constant? Interesting. I will have to research that particular requirement. For now, it is easy enough to comply by declaring the timer instance variable, but not assigning it until the constructor is invoked:
class PrettyStopwatch { Stopwatch timer; PrettyStopwatch() { timer = new Stopwatch(); } start() { timer.start(); } stop() { timer.stop(); print("Elapsed time: " + timer.elapsedInMs() + "ms"); } }With that, I am back in business (code compiles and runs as before). The last thing that I would like to try tonight is making a "named constructor". That is, I hope to be able to instantiate and start my "pretty" stopwatch on a single line. That turns out to be quite easy—I simply define a
PrettyStopwatch.start()
method in addition to the regular PrettyStopwatch()
constructor:class PrettyStopwatch { Stopwatch timer; PrettyStopwatch() { timer = new Stopwatch(); } PrettyStopwatch.start() { timer = new Stopwatch.start(); } start() { timer.start(); } stop() { timer.stop(); print("Elapsed time: " + timer.elapsedInMs() + "ms"); } }With that, I am down to two lines of code required to start, stop, and print out the results of my timer:
main() { final doom_finder = new DoomsDayFinder(); var timer = new PrettyStopwatch.start(); doom_finder.spawn().then((port) { port.call(2000).receive((message, replyTo) { for (var year in message) print(year); timer.stop(); }); }); }(try.dartlang.org)
And it all works.
I was unsure of the named constructors—both how to write them and if I cared for the aesthetics. Writing them turns out to be fairly easy. More importantly, I must confess that I do like using them. They cut down on the parenthesis madness that Javascript chains might require:
var timer = (new PrettyStopwatch()).start();Named constructors seem an especially big win when there are arguments—those get unreadable quickly in Javascript.
It is a bit ugly to define both a
start()
named constructor and method. Perhaps that is something that be cleaned up when a method_missing or reflection capability is added to the language.Day #258
No comments:
Post a Comment