Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Why on earth would you want to compile javascript (which is what typescript essentially is) to wasm?


If nothing else, it results in a smaller download than minified js. (I believe that's true even today.) And, in theory, it should be able to run a bit faster also. Not sure if that one's true yet.

Update: Here's a quote from the Microsoft announcement:

"Despite being an early implementation, the demo starts-up significantly faster than just using asm.js as the WebAssembly binaries have a smaller file size and parse more quickly than plain JavaScript that needs to be parsed in the asm.js case."

https://blogs.windows.com/msedgedev/2016/03/15/previewing-we...


You are misunderstanding. A C++ application compiled to wasm is smaller than a C++ application compiled to a subset of javascript.

A javascript application compiled to wasm doesn't really make sense. Javascript isn't a compiled language. The best you could do would be to store some kind of compressed representation of the source code, along with a JIT compiler to run that source code. It isn't a sensible thing to do.


Once WebAssembly supports all the features of JavaScript, which is on the roadmap (step 3, "everything else" [1]), it'll be a very sensible thing to do, especially for mobile.

Compiling JavaScript text source code into a binary representation of its AST will save time and space downloading, and time starting up.

You won't need another JIT compiler, the web browser usually already has one. WebAssembly is bytecode and JIT agnostic. Compiling text JavaScript into a binary WebAssembly representation of the parse tree is different than compiling the parse tree to bytecode, or JITting the parse tree or bytecode to machine code. They are complementary layers, and both synergistically useful together.

[1] http://bytecrafter.blogspot.nl/2015/06/a-quick-overview-of-w...


I can only imagine the possible security exploits available by passing AST binaries directly to the browser, rather than letting the JS lexer/tokenizer and compiler enforce language rules from the source.


Luckily, the designers of WebAssembly imagined those things before you.


That's true of version 1, but supporting arbitrary JavaScript is on the roadmap.


The wasm AST is also a language, and a very simple one at that. Much easier to test and fuzz than all-out JS.


A javascript application compiled to wasm doesn't really make sense. Javascript isn't a compiled language.

This compiled/interpreted distinction has gotten quite fuzzy, and it has been for decades now. Smalltalk was always a compiled language with really late binding. It did compile to a bytecode which was interpreted at first, but that became JIT compiled in all but one commercial VM. This all happened over a decade ago.

Also, there is clearly a subset of Javascript programs that could be usefully compiled down to a small, fast, compact machine language program.


> there is clearly a subset of Javascript

I suppose the extra restrictions of Typescript would help. At least if you add extra restrictions to make it easier to compile.


Sure it does. Do you know that Lisp and Scheme have compilers? They target assembly even as dynamic languages, like JavaScript.

These are totally sensible. Look at: http://www.call-cc.org/


But the point is, if you want to compile your JavaScript code ahead of time, you have to ship your own GC and JIT compiler, because you no longer get it "for free" from the browser's JS implementation. There's absolutely no benefit from doing this.


That will soon not be true. Exposing the js gc is on the roadmap.

...which will also make it feasible to use other gc:ed languages without shipping an enormous runtime.


Okay, but why would you compile JS down to wasm, only to have it then use the browser's built-in JS runtime? I see the use for compiling other dynamic languages, but compiling JS via wasm shouldn't be any different than running it via the normal JS engine, aside from potentially having a slightly smaller executable.


But they will still need to be interpreted ie cpython.

I'm not sure how much space just cutting out the GC will save?


GC is only a small part of a high level language runtime.


Nitpick: What doesn't make sense is 'compiled language'. The term is non-sensical. Languages are not interpreted or compiled, implementations are (sometimes both like cpython). As a counter example, cl-javascript[0] compiles javascript to common Lisp

[0]: http://marijnhaverbeke.nl/cl-javascript/


> Javascript isn't a compiled language

I mean, it is if you compile it to wasm. It is definitely JIT compiled.


Then you have to ship your own GC with it.


I think you misunderstand what WebAssembly is about.

As I understand it, it's little more than a binary serialization of JavaScript ASTs. In which case, no, you don't need to ship your own GC with it.

I mean, you could always write a JavaScript interpreter in JavaScript, and then compile that into WASM, in which case, yes, you'd ship your own GC. I don't see why you would feel the need to do that for real world applications, though.


> I think you misunderstand what WebAssembly is about.

I don't, WebAssembly is about C++, primarily. Every design decision has been to support C++. Everything else is an afterthought that will come later. WebAssembly isn't about minifying your JS.

Read this: https://github.com/WebAssembly/design/blob/master/GC.md GC, DOM access, etc. don't exist in WebAssembly code, yet.


It's C++ first as a convenience, since LLVM is best at C++ and emscripten w/asm is a solid benchmark. It is NOT primarily about C++ just because that's the v1.

https://github.com/WebAssembly/design/blob/master/FAQ.md#whi...


It's not about C++ primarily, it's about building on the base which asm.js laid out. C++ would only feature in this because of Emscripten.


WebAssembly is a compact serialization of asm.js, not of arbitrary Javascript.


That's true of version 1, but supporting arbitrary JavaScript is on the roadmap (step 3, "everything else" [1]). Which will be awesome!

What I'd love to be able to do with tools like Unity3D that compile C# and other CLR languages into asm.js, would be to pass JavaScript objects directly in and out of the C# code so you can manipulate the underlying JavaScript objects directly from C# with little or no overhead.

Right now of course you can implement JSON libraries in C#, but it's indirectly and inefficiently layered on top of the flat memory model of asm.js. I want to be able to use the native JavaScript objects and libraries directly from other languages like C# that compile into JavaScript. That would be ideal!

To do that, asm.js would need a way to store references to garbage collected JS objects somewhere, somehow, using proxies or handles represented in linear memory, opaque reference types [2], or some other magic like that, like Apple's JavaScript/Objective C bridging stuff [3].

[1] http://bytecrafter.blogspot.nl/2015/06/a-quick-overview-of-w...

[2] https://github.com/WebAssembly/design/blob/master/GC.md

[3] https://developer.apple.com/library/mac/documentation/Cocoa/...


Interesting. But then it wouldn't really be compilation, but parsing + serialization. I guess the distinction is rather pointless.


This conversation was confusing until I read this point


My initial reaction was for software with a flat memory footprint, so it really doesn't require garbage collection. Our application could be written in C, if we weren't web developers who are working in JavaScript.

No one wants to do web development in C++ honestly, but they would like the performance.


I could see this functioning really well with webworker once some sort of thread-safe representation is in place for quickly moving objects in/out of said worker... Would be a pretty clean separation of WebAssembly code, and the DOM accessible code by convention... even if sticking to object serialization (JSON), it would be pretty clean...

With IE9 support slipping, it seems to be a no-brainer in terms of support at this point too [1].

I'm also thinking this could be a huge win once it hits node.js (v6?), as this could be a great answer to better binary module support. As binary modules are a bit of a pain to support, and prebuilt binary modules are in a hodge-podge state.

[1] http://caniuse.com/#feat=webworkers


Yes, it would be faster.


Why would bundling a Javascript engine in a webpage be faster? I guess it's likely if someone were to make an improved Javascript engine, but their effort would be better spent improving the Javascript engines in browsers (affecting all webpages) rather than bundling it as a many-megabyte download into their own webpages.


DonHopkins pointed out that wasm will eventually support serialization of arbitrary js. So you wouldn't need to include the js runtime at all, but still get a much quicker download and parsing.

https://news.ycombinator.com/item?id=11291997


It really depends on the code. This whole topic is for webpages with scripting that have reached performance bottlenecks, not just an obscure exercise in torture.


> Why on earth would you want to compile javascript (which is what typescript essentially is) to wasm?

Similar to asking why would you want to run JavaScript on the server?

There's something to be said for having your code in a single language. People can move to different parts of the project more easily and if you need to run the code in multiple places then you can do so with (mostly) a single codebase.

The real question is why WOULDN'T you compile all your JavaScript to wasm assuming the build process is easy enough. For complex site that already have a build pipeline I don't see any reason to publish minified JavaScript instead of just building it all into wasm for performance reasons (assuming mature debugging tools of course). The only question I'd have is whether you get that much gain by going from JavaScript to wasm or if the browser's JIT compiler can do a good enough job.


Compiling JavaScript into WASM is most likely not going to result in better performance unless you make an extremely good static optimizing compiler, and probably not even then. It's very hard to do the kind of optimizations that JIT compilers do ahead of time, in one single static binary.


Agreed. The entire point of asm.js (which WASM is currently just a compact encoding of) is that it's a simpler subset of javascript that's easier to optimize. If you could transform arbitrary Javascript into asm.js efficiently, then similarly you could also apply asm.js's optimizations to arbitrary Javascript, and the whole asm.js part would be pointless.


Pull the developers (or poll them) from V8 and ask them what they think.

All of the "just-in-time" optimizations can be done ahead of time. Which saves [that much run time x that many users] in computer time.


Everyone on V8 would disagree with you :-)

Type tracing in particular is the big win, and with a dynamic languages you simply can't prove enough to do it ahead of time. There's also startup time that you're paying with AOT and avoiding with JIT.


> Type tracing in particular is the big win, and with a dynamic languages you simply can't prove enough to do it ahead of time.

The post I originally replied to brought this up in the context of TypeScript with the aside that TypeScript is basically JavaScript. Do you think that using TypeScript's static typing and compiling to wasm could/would be faster than JIT-compiled JavaScript?


I don't know why you refer to V8. V8 isn't doing AOT compilation of general JavaScript.


Once webassembly is widely supported, why would we ever write JavaScript again?


Because DOM manipulation in C++ sounds like a nightmare to me.


If you want it to be fast, you probably shouldn't touch the dom.


To the contrary, I think everyone should touch the DOM when they need the DOM. If this is going to be a platform for more than ads and shitty games, it will need to be able to use the browser's exquisitely engineered ability to do text rendering and layout.

Just like Flash or the JS game platforms that are stupid hacks on top of the canvas element, if people have to implement text rendering without the DOM, it'll encourage putting poorly-rendered text in unusable layouts with squirrely scrollbars. We can do better.


I mean you would do it the react way and only manipulate an abstract representation of the dom.


C++ speed in the browser... just be sure not to touch the browser.


I was thinking more about Ruby, Python, or go


It probably won't happen in V1 but yes, it's incoming. We'll be able to pretty much use whatever we want. When wasm was first announced Brendan Eich made this clear, and a lot of the JS-All-The-Things folks who bet their careers on it were upset.

I'm not sure why, if you like JS, people can keep on using JS indefinitely. My theory on programming is to use the language that I prefer, and worry about everything else secondary. For me that's Python. I've mostly avoided any deep dives on learning JS so it'll be nice to be a part of a budding Python web frontend community when the time comes.


I'm getting somewhat excited about swift. It's quite a modern language syntactically and python/ruby-like productivity may not be out of reach. Yet it leaves managed languages in the dust performance-wise (factor 100x plus), on par with C++.

And the memory management is uses should make compilation to WebAssembly rather straightforward. (... I believe – I have little knowledge of that sphere and welcome any corrections).


Wouldn't you still have to ship the entire python VM? That doesn't sound to feasible for your average web app.


Once wasm supports some access to the gc (on the roadmap), It should be feasible. You wouldn't reimplement the entire runtime, but reuse functionality (like the gc) from the js runtime.


Do you have any reference for that? You can already technically use whatever you want and wasm will not remove the need for high level languages also having to supply a (multi megabyte) runtime as there is no direct mapping to wasm instructions unlike with C++ or C.


Eich's comments on HN and on Twitter. It was all discussed when wasm was first announced a while back. I'd dig up the exact source comments from Eich, but at work. You'll probably see enough comments from the wasm folks in this post to verify whatever particular technical specs you're interested in to satisfaction.


Game dev here.

Speed. Oh and memory - if I could optimize it so that all our vectors, matrices and logic code did only stack allocations I would be a happy camper.


Even Pascal from FreePascal + Lazarus gets better speed than JS with a JIT :S

Why don't you compile into native platforms?


Performance.

Looking at dependencies for certain key Javascript libraries makes me skeptical now that this is possible.


Why would AOT compiled JS performance be better than the highly advanced JIT compilers that are _designed_ to run JS efficiently?!

AOT compiling highly dynamic languages gives you very little room for optimizations.


Because even a just-in-time compiler is slower than native performance quite frequently. A just-in-time WebAssembly compiler can be guaranteed to be as fast as V8 in practice.

Branch prediction on a CPU can be quite helpful, but if a program stops hitting the same branches it can impact performance. The point of a just in time compiler is that it compiles on the fly, which does take a certain amount of time. That could be loading time for your application.

In any case, the purpose of this development would be to design something that is faster than V8. And I'm specifically speaking of compiling with inferred types or from asm.js or TypeScript, not embedding a VM or a garbage collector or an emulator.

This compiler might only accept programs that would be faster.


Well, you'll need a garbage collector anyway, and with AOT compilation it would have to be conservative (which isn't that much of an issue, but precise collectors are generally a little more efficient).

The problem is that you can't fully trust your type inference. JIT compilers can get away with this because they can escape to the interpreter if a type check fails. With an AOT compiler you can optimize for your inferred type but you still always have to include complete code for the slow path too. At that point 80%+ of your instruction cache is gonna be probably-unused code. You can never eliminate as many type checks as a tracing or block versioning JIT.

TypeScript doesn't help either:

  function foo(a: int, b: int) { return a + b; }
  window['fo' + String.fromCharCode(111)]('nice ', 'try);
Whoops. TypeScript is (intentionally) unsound, which doesn't help your compilation much.

If AOT compilation were a way to get JavaScript faster than V8, V8 would compile ahead-of-time (well, it would probably compile in the background and use an interpreter on first load, but you get the idea).

asm.js is a different since it is strongly typed and explicitly controls memory layout. It's not JavaScript from the perspective of implementation.


Well, then I should use some regular expressions, a parser generator, AST walker and syntax analyzer, with the help of a few directive comments, to turn my strict subset of JavaScript code into C, and then use emscripten to generate WebAssembly.

Then I will have faster (and smaller) code on platforms that support WebAssembly and regular JavaScript on platforms that don't.

What a wonderful way to deploy JavaScript to WebAssembly for enlightened developers, which doesn't involve a "compiler."

Obviously, we are thinking of different scenarios. My subset of JavaScript may be different than yours, which might be different than asm.js. Asm.js would be great except it isn't idiomatic and having a fixed heap isn't always great. That doesn't mean there aren't middle grounds which are as of yet unexplored. This is sort of a limited area, which is probably why no one's started a project on this yet.

By the window['foo'] argument, minifiers are unnecessary because then you can't use eval().


There was an experiment ("strong mode")[1] of a subset of JavaScript that is way higher level than asm.js but it failed [2].

1. https://developers.google.com/v8/experiments#strong-mode

2. https://groups.google.com/forum/#!msg/strengthen-js/ojj3TDxb...


That is interesting, thx. ... but it seems to me, they failed, because they wanted to mix strong typed js with weak typed ... "the main problem here was the interoperability with weak classes: we need to allow inheriting strong from weak classes and vice versa"


> turn my strict subset of JavaScript code into C, and then use emscripten to generate WebAssembly.

Well, the problem there is that your subset would be... C. JavaScript without automatic memory management, closures, prototype inheritance[1], and dynamic types isn't really JS anymore.

> By the window['foo'] argument, minifiers are unnecessary because then you can't use eval().

Most minifiers don't touch object properties or global variables for this reason. Closure compiler is the only one that does and it's quite strict (and doesn't work on a lot of JS code because of it).

1. Assuming objects are hash tables in your implementation, you might be able to do inheritance by reference counting a list of parent hash tables but that could get messy.


The code that I have to work with is static. It just happens to be JavaScript. Aside from writing some type casts and a linked list implementation, the standard implementation for a project like this doesn't have to be large. And yes, it boils down to a trivial C compiler.

Also, Uglify 2 modifies global properties if you tell it to, and neither uglify nor closure compiler do well with object properties, which can be renamed.

All of these arguments assume that a developer is unaware or not understanding of the mechanisms that their code uses. It seems no one is interested in using anything other than emscripten/LLVM.


>Because even a just-in-time compiler is slower than native performance quite frequently.

No that's not how it works. The problem with most JIT'd languages is that every variable or field is a pointer, every function call is a virtual call and there are no type signatures to help a compiler. These are the main reasons. If you added structs, nonvirtual functions and type hints you will quickly enter C performance territory (this is basically what asm.js does).

JIT compilers heavily use profiler guided optimizations to avoid the overheads associated with dynamic languages. They can often inline polymorphic function calls because usually 98% the variable points to an instance of type X and the remaining 2% to type Y. Falling back to a normal polymorphic call if the type is not Y. This is something an AOT compiler cannot do.


> This is something an AOT compiler cannot do.

Yes, it can. You know the part where the JIT decides whether to execute X or Y? That can easily be implemented in a conditional in compiled code with the two code paths, X and Y.

But I'm more interested in the C performance territory. I'm not even interested in cross-compiling code where globals are used or variables change types.

It's possible to strip the functions and properties off of a JavaScript prototype and if it's well behaved, which user code is more likely to be than JavaScript libraries, it can be compiled fairly well.


> You know the part where the JIT decides whether to execute X or Y? That can easily be implemented in a conditional in compiled code with the two code paths, X and Y.

And that's the difference with a JIT compiler: if the value is almost certainly X, then it just emits the code for X and a stub for Y. The stub just bails back into the interpreter. The check is a couple machine instructions and the fast path can be pipelined (since branch prediction is unlikely to fail).

An AOT compiler has to include the full code for both X and Y, no matter how unlikely Y is. AOT compiling dynamically typed languages gets you easily 80%-90% unused code.


Then why isn't your argument against code size rather than performance? Seems like an odd position to take. The fast path would also be branch predicted in an AOT case.

The only difference in this hypothetical is that the slower path would run faster.


Because with 80%+ unused code, your instruction cache is gonna choke.

Also JITs can remove many more type checks, because it knows when a check would be redundant. See e.g. Lazy Basic Block Versioning[1], but existing tracing JITs do quite well also.

1. http://arxiv.org/abs/1411.0352


Native performance is only better in the cases where you can explicitly control memory layout & access. That's why asm.js runs so fast. You're explicitly translating C/C++ to arrays.

I don't really see how a js -> wasm compiler fundamentally changes things. You're still working in JS which has poor memory placement semantics.


WebAssembly allows for a stack and a linear area of memory. The job of the compiler is to determine memory placement.


Argh, I see this keep coming up and it really needs to be put to rest.

Compilers don't know how to layout your data. They don't know how you'll access it or the traversal patterns. Your whiz-bang compiler isn't going to strip out class members and AoS from SoA because that's a fundamental data structure problem.

Compilers are great, they fold things down, inline and unroll loops. When it comes to memory placement they can't know your intent and it's up to you to lay out your data appropriately. They might do padding but anything else is going to have memory & complexity implications and they shouldn't make those decisions for you.


I don't know, you have a real mix of arguments here, as do most people. There's nothing a JIT does that an ahead of time compiler can't do without the burden of a larger footprint.

This is really an issue of backend optimization to "make things like asm.js."

For example, there are obvious examples of cases where a JavaScript object's properties and property types would be transparent to a compiler at compile time, with a complete graph of where those values would be stored and used. This would be stored in the WebAssembly stack, analogous to an asm.js fixed array.

The WebAssembly sandbox is designed to run code directly. The JIT is designed to build code to run directly in an iterative fashion. If system designers knows how software is expected to operate, they can make choices to instrument that process and also make software which is designed intelligently.

Java runs in a VM. Someone could write a just in time compiler for .java code that performs well. That's not a sufficient argument not to develop or continue to develop a javac compiler for byte code. Additionally, whether or not a language is designed to use GC doesn't mean there couldn't be research or design into avoiding or augmenting that situation for performance (in the way that a just-in-time compiler would relieve the situation). Nor reason not to build a platform and engineering methodology to deploy to two independent and cooperating runtime environments.

Neither Asm.js and emscripten or C are the end of all things. Neither is dynamicism.


If you compile ahead of time, you can tune your optimizations. With the right tooling you can tell the compiler that a certain path is hot and should be optimized from the beginning, or catch deoptimizations better, or just get rid of the compilation cost. Right now I'm not sure how much practical benefit there is, but there's a lot of potential.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: