Friday, September 13, 2013

Using Dart - a summary of my experience

On my list of languages that I hate with passion JavaScript takes a second place, right behind VHDL. So when I thought about creating a Web UI for PSHDL, I started with GWT. GWT is nice in that I can use Java for everything and it works mostly well, but ultimately I wanted to have the ability to run simulations in the browser. Using GWT to run simulated code is awfully slow. So that was not an option. So I was looking on how to put some Lipstick on that pig called JavaScript and found TypeScript. Well, its definitely better than pure JavaScript, but it's not what I was hoping for. It really is just a thin layer around JavaScript, but I wanted something that makes simulation really fast. So I found Dart.

What's awesome about Dart?

The thing that I liked most about Dart is that I took me very little time to pick up. It is in many aspects so similar to Java that I had very few surprises so far.

I also like that it comes with its own VM, which is generally faster than the JavaScript VM. While that alone would be enough to drive me to use Dart, this VM has also arbitrary arithmetic built into it! This is pretty awesome for my application where 128 bit signals are not unheard of. And in fact, right now, Dart is probably the fastest way to simulate PSHDL when the bit width exceeds 64 bits.

Speed

Even with the burden of having to take care of arbitrary precision integers, the VM is slowly approaching JVM speed, which I find really fantastic. In order to run in the browser however you need to either have a browser with built-in Dart VM or compile to JavaScript. While the chances of having a browser with a DartVM are close to 0 right now, it eventually might happen, but if you are serious and want to get some simulation speed out of the browser, a user might just install Dartium for that reason. The most likely situation however is that the dart2js compiler will be used to create JavaScript code that runs in every browser.

Web-ui

This is another advantage of Dart over TypeScript, there is some Web UI building stuff included, and also some very important things are built-in. For example there is really no need for jQuery, Dart already has some query function that you can use.

IDE

As a fan of Eclipse, I am very happy to see that a lot of work is put into creating an IDE that is enjoyable to use. For TypeScript an Eclipse plugin has been released just recently, but I bet the quality of the Dart IDE, which is an Eclipse RCP, is higher.

Language

Some of the language constructs are pretty nice. I especially like the .. notation for initializing objects. It allows you to chain methods calls as if they were returning the this object. Example:

TestResult.addTest(new Test("Adding positive numbers", 10)..progress=5..status=Test.CANCELED);

is equivalent to:

Test t=new Test("Adding positive numbers", 10);
t.progress=5;
t.status=Test.CANCELED;
TestResult.addTest(t);

I like this so much that I actually which this would be in Java. Btw. my AST Model is designed in such a way that you can do this, but each method call is returning a new immutable object.

Like most modern languages and Java 8 it also has functions as first class objects and closures, which makes filtering tasks very smooth. There are a few other little things that I like, for example get/set declarations.

What sucks about Dart?

Creating a language is hard, especially the validation part. So it is not very surprising that I encountered and reported a few bugs here and there, but one of it is so severe that it makes me question whether google is serious about Dart or not.

Dart2JS

Fact is, right now the chance that someone is surfing the web with a Dart enabled browser is close to 0. So the dart2js compiler is VERY important. If this process fails, Dart is useless. Whatever you do in Dart, is has to be translatable in some way to JavaScript. Unfortunately this is not the case for arbitrary precision arithmetic. The feature that I like most about Dart is broken in JavaScript. Not just by a little, its a wreck. You can argue philosophically if there should be a difference for this piece of code:

var x = 123;
print(x is! double);

which will print TRUE in Dart VM and FALSE in JavaScript. But the fun is over when the arithmetic is off:

int billion = 1000000000;
int quintillion = billion * billion;
int quintillionOne = quintillion + 1;
print(quintillion == quintillionOne);

Because in what must be one hell of a party some drunk person of the dart team made the joke of using the javascript number as translation target for int. Well, what could possibly go wrong... This is not an issue that was discovered yesterday and the team had no time to fix it just yet. This has been known for more than 1,5 years now! There is not even a compiler warning that tells the programmer that something might not be right here!

To be clear what the problem here is: The dart team integrated a feature into Dart (arbitrary precision arithmetic), which they are unable to implement properly in JavaScript, with no warnings or possibility to work around just yet. As I said earlier, being able to run in JavaScript properly is really important.

For PSHDL this means that the simulation is currently limited to a maximum bit-width of up to 32 bits. After that bits are lost and the simulation is incorrect when run in JavaScript.

A purely cosmetical issue is the fact that dart2js takes 3.5s for a very simple dart file and produces an obscene amount of code around, which is caused by the fact that each dart2js invocation kind of becomes its own complete application with all APIs included and everything, but I will come to that later again.

Language

At least one bug that took me one day to find was caused by the lack of enums. But there is light on the horizon, someone is working on it and it will be available post 1.0 probably.

Another bug that I produced was caused by the fact that this code does not even generate a warning:

int doStuff(){}

When you call doStuff, it simply returns null... This is not what I expected, but oh well, some people like it that way..

Another thing that I can get my head around is the package and library system. I somehow manage to import my stuff and am able to use it, but I still don't understand what I do when I place a

library filelisting;

at the top of the file. Sometimes you need it because if you include two files that don't have it, Dart gets confused somehow. But its not like you need that anywhere... Maybe I am really just missing something here that is totally useful, but for now I just accept it and put something random at the first line so that the compiler is happy. I am also not the biggest fan of the URI based imports.

Dynamic loaded code

When I started to implement the dart code generation for simulation, I was wondering how I could actually load some code at run-time. The solution to that are called isolates. In principle a nice multi-threading concept. You create a separate process for the loaded code and communicate via message passing. So far so good. But this also implies a heavy performance overhead, because all your data is serialized and deserialized for every Message that you send. No shared memory, nothing. This makes it also quite cumbersome to send some data. My first idea was to have a simple recipient on the generated code side that receives values to set, make a run and return ports that changed. The performance of that was awful! The reason is quite simple: For the message passing Maps are used and copied in between processes. I then used another method where the input for the generated code is generated within the simulation process. The UI just sends some configuration data to the simulation process, which then runs until something changes. Then it reports those changes back. How that looks like can be seen here.

As those processes do not share anything, the dart2js compiler has to include all required dart APIs within the javascript source, which explains why the resulting javascript source is so big. A more light-weight concept with shared resources, comparable to the dynamic class loading in Java would be awesome. This could significantly improve the performance of my simulation as the message passing bottle neck would vanish.

Another thing that I learned, when working with isolates debugging becomes really hard. You can't set break points in the isolate and it sometimes crashes without propagating the exception properly.

Summary

I really enjoy programming in Dart. While the frequent updates to the Dart SDK cause some slight shivering when I see that yet another update is ready, the overall stability is good. You can't blame the Dart team for breaking API changes that cause some trouble in this early stage of Dart development.

But whether I recommend someone to use Dart depends on the dart2js bug. If you know that you will not be affected, I can recommend it. But it also shows that the designers of dart dreamed up some concept that they can't deliver right now. I really hope that this is fixed soon and if they deliver a 1.0 with this bug still open, I will call them morons and slam my door really loud, but very certainly I will not recommend Dart to anyone then.

No comments:

Post a Comment