Why dart2js produces faster JavaScript code from Dart
news.dartlang.org
news.dartlang.org
It can see every place it gets assigned. If it's never assigned from something that can be null, it can't be null. Of course, that requires global inference to determine the possible types that the RHS can be. dart2js does that with increasing sophistication.
> Maybe an external caller sends null to a method not expecting it.
dart2js is a whole program compiler so it can make closed world assumptions like this. At the point that it's compiling, there are no "external" callers. It can see every callsite in the entire program.
> Or, can you not call Dart compiled code from JS?
Yes, Dart does have a JS interop story[1]. We're still working on it, but, by design, it's not as seamless as say CoffeeScript. It's an actual interop process and not just "it's all JS so it can all call each other". I think that helps dart2js control the places where unknown values can leak in from JS.
Doing whole-program analysis seems like it would restrict your deployment methods, right? It's fairly common in the JS world to be calling into libraries that are split into separate files and hosted on external servers. Something like jQuery you do it for the load times, something like Google Analytics you do it so that Google can push updates without you needing to redeploy your script. There are also possible use cases with lazy-loading libraries for load times, or only loading scripts on certain pages.
Does the whole-program compiling approach mean that I would have to import whole libraries into my own project in order to use them, and that I can only deploy single script files? How does the whole-program approach interact with event handlers embedded in HTML, which it would not have visibility into?
I would expect that some of these restrictions could maybe be eased in a native-Dart client. But given that for the foreseeable future most Dart projects will have to target non-Dart-enabled clients, in practical terms Dart as a whole will have to be shackled to any limitations in Dart2JS. I'm curious what your thoughts on this are and if you have any plans to address it.
Dart2js needs to see all the libraries that are used. It performs tree-shaking to remove unused parts and then compiles the rest to JavaScript. By default dart2js produces one big JavaScript file, but it can cut your program on library boundaries that can be loaded lazily. This is still work in progress (only allows to split into 2 files so far) but looks promising.
The lazy loading needs to be done by the user before parts of the lazy library are used.
I don't see how event-handlers change the game. The html-library is a library like any other.
While I do believe our Dart/JavaScript interop story will continue to be refined, I do want to point out that the days of javascript: URLs and eval are nearly over. The Web is getting a stronger security model through CSP [1] (content security policy). New restrictions put in place by CSP include turning off eval, new Function, inline JavaScript, and more. This is a very good thing, because it reduces the attack vectors for XSS and more.
[1] http://www.html5rocks.com/en/tutorials/security/content-secu...
Sometimes, but I think it's actually more common to do the opposite: minimize the delay by concatenating and minified all of your JS files into one big blog. That way there's only one network roundtrip. dart2js follows that path.
> something like Google Analytics you do it so that Google can push updates without you needing to redeploy your script
For stuff like this where you just have multiple completely independent scripts, you can just have separate <script> tags.
> How does the whole-program approach interact with event handlers embedded in HTML, which it would not have visibility into?
We actually do have visibility there. Dart has its own DOM library and dart2js has pretty deep insight into how to interact with the DOM.
I don't want to focus overmuch on the specifics of the Google Analytics example, but it's illustrative so I'll continue. While GA can be isolated, if you want it to track any events that involve your script code, they need to call out to the API that GA loads onto the page. Its their intention that they can push code updates to my page (which may change how it communicates to GA servers), without me needing to redeploy my own code.
The analytics world is now proliferating with a number of script-loader services that serve the same purpose: update tracking (including interacting with other parts of the page), without integrating into the deploy process. There are plenty of arguments that this is a Bad Thing, but nonetheless enough people are willing to pay for this service to keep afloat multiple companies where that is their only product.
It's totally possible to load scripts like that in via the JS FFI, especially ones with a well-defined API. But, if both parts are separately Dart, it would be nice if they could integrate more easily than round-tripping through JS. Among other things, it would be nice to have the type information carry through.
So that's where I'm coming from, and the use cases I'm interested in. And if you say that those development practices are something you don't want to encourage I wouldn't entirely disagree. It does seem like something rather different than the approach your taking, and the best way to reconcile it would be for library authors to publish a header file for functions/types that Dart2JS could assume to exist. Dunno if that's a route you would want to go.
I think people often use javascript libs on a CDN because they don't want to go to the hassle of setting up a javascript package management system, or figure out which file to download and where to put it. It's not all about load time savings.
Dart's minification, combined with pub, the package management system, make the CDN usecase irrelevant for dart IMHO. A business can just ship their library on pub, and it's easy for people to use because of Dart's out-of-the-box tools.
[1] http://api.dartlang.org/docs/releases/latest/dart_async/Defe...
It seems to me that if we're going to migrate away from JavaScript, let's get a serious performance boost while we're at it.
With that being said, I don't believe in anything with a weak interop story unless you are talking about utilizing legacy code, for which there is none for Dart but a lot for asm.js (and pNaCl, for that matter.) So I don't really see why Dart would fare better than GWT.
http://www.quirksmode.org/blog/archives/2011/10/dart_or_why_...
The Dart team is very aware that it is highly unlikely that the DartVM will be put into any browser except Chrome (and there is no time-table on when that will happen). That is why their Dart2js compiler is seeing so much attention from the team.
Dart, to me, is Google's new GWT, but trying to align more with the web as we know it today (instead of hiding the DOM from its users). Even if Dart is only ever cross-compiled to Javascript and used that way in production, I would prefer to code in Dart than Javascript for anything that requires more than a few lines of javascript to implement.
Nobody thought JS and Ajax was a serious thing until Google Maps came about and everyone's jaws dropped. Despite all the academic or theoretical benefits async requests it might have had, they didn't become popular until a killer application came about.
I am also thinking Dart for Android? I wish they had Python for android, but oh well, I understand it was much more of a political thing, but I can see Dart+VM being that platform.
Seems sensible for google to have some options similar to Java for both Android, and their in-house server-side code. (Oracle anyone?)
...even better performance? See the light-blue line on the graph in the OP.
See the benchmark games: http://benchmarksgame.alioth.debian.org/u64/benchmark.php?te...
What's crazy to me is that SBCL still stands up toe-to-toe with say Mono (3.x, using LLVM) (or GHC or the JVM): http://benchmarksgame.alioth.debian.org/u64/benchmark.php?te....
This is a compiler that hasn't even heard of SSA, nor any other advance in low-level optimizations in the last 15-20 years. It also achieves parity with Java on binary-trees, even though that's basically a GC benchmark and SBCL has a fairly primitive one.
It's a testament to the power of a well-tuned compiler using relatively simple algorithms and a language that is pretty amenable to optimization despite being highly dynamic.
(declare (optimize (speed 3) (safety 0) (space 0) (debug 0))
(type sb ,c)
(type (simple-array sb (,n)) ,copy))Well keep in mind that every other language that compiles to JS is generally slower, so any improvement here is pretty impressive.
Note that this is just the performance of the Dart code compiled to JavaScript. Dart code running on the native Dart VM has very different, better perf.
What he or she is wondering is why one would bother with dart if it's not much, much more Runtime Scorey than JavaScript (V8).
Due the nature of the Dart language the DartVM will make a number of optimizations possible that are not even possible in V8. So it will be a better platform for continued performance improvements. Time will tell...
To be honest, even if it was only doing 0.5x, I'd still use it because the tooling makes me more productive.
Why the "still"?
If I don't have to use JS then it is worth it even if it was about the same speed.
Have you ever written a somewhat bigger JavaScript application with a few thousands lines of code spread across dozens of files? It's horrible.
With Dart, the experience is similar to Java or C# (just with terser syntax). There are classes/packages, and you can simply import things. In the IDE you get call-tips, auto-complete, and sanity checks (based on type annotations or inferred types). There is very little friction in general.
There is also block scope, a lexically scoped `this`, built-in classes/inheritance, mixins, lambdas, and things like that.
DeltaBlue:
100 / 320.84 * 512.74 = 159.81 -> +60%
Richards:
100 / 444.00 * 814.09 = 183.35 -> +83%
[disclaimer: I work on the Dart team]
for (int i = 0; i < v.constraints.length; i++) {
...
c = t1[i];
...
}
Does it do that optimization because it knows v.constraints is fixed length or because it knows that i can never be bigger than v.constraints.length? for (int i = 0; i < list.length; i++) {
var t = list[i];
}
Things get more complicated when there are function calls in the loop-body that could potentially change the list-length: for (int i = 0; i < list.length; i++) {
foo("random call", list); // could have side-effect.
var t = list[i]; // needs to check bounds.
}
However if the element is read before the call, it should still work: for (int i = 0; i < list.length; i++) {
var t = list[i]; // no need for bounds-check.
foo("random call", list); // could have side-effect.
}
The last example doesn't need a bounds-check, but it does need to reload the length-field of the list at every iteration (in case the length changed).