Hacker News new | past | comments | ask | show | jobs | submit login

Imagine there would be a language that would compile to proper bytecode (not JS), that would run on a standardized platform which is present on almost every computer, that is mature, sandboxed, and actually pretty fast. Oh, wait, that already exists and is called Java.

Java has gotten a bad rep lately due to some high-profile drive-by-malware bugs. But if the java codebase would have gotten the same intensive care that the webkit codebase got, this would no longer be an issue.

Many people remember java to be sloooow. When I first came into contact with it in school, that was certainly the case, but since a couple of years it has had a modern JIT that could easily rival native code.

Java applets are ugly, sure, but that is largely due to the decades old AWT, and the poor font support it used to have. With SWT, you can have native widgets (dunno if they work in Applets, but they are nice on the Desktop), and with antialiased drawing you can get the same results as with HTML5 canvas.

Java applets (and Flash, and Silverlight) died for marketing reasons, and political reasons. There were no unsurmountable technical issues. The outcome is that we are stuck with "worse is better" for the foreseeable future, only max. 50% to 1% of the possible native performance, and a bunch of restrictions we only slowly realize what they mean (no sockets, no signed applications, no anonymous/serverless mashups, less hardware access than we used to have, suboptimal caching, suboptimal tooling like languages, debuggers, content creation tools (I haven't seen anything that can replace Flash for simple vector animations yet) and so on.

On the web, when one thing just works, albeit slowly; and another thing requires installation but runs quickly; the thing that just works is likely to win.

Unless java gets upgraded to a first class browser component, JavaScript will tend to win. As a product designer, every step I take my user through loses users. Installing java is a big, scary step that I can almost always avoid.

The insurmountable issue is that it requires users to do installation work.

Well, until about a year ago, Java was on (I'm guessing) 70% of PCs, Flash on > 95%. Now with the shift away from plugins, and the growing importance of mobile, its shrinking quickly.

But! in the brave new world of HTML5 and so on, you still can't assume that everybody has all these features. Either they are stuck on older browsers (at work, or my old laptop that I rarely use), there are subtle implementation differences bewteen browsers (although I have cutting-edge Android devices, the cool demonstrations often don't work nicely in them), or finally the browser is OK, but the computer is too slow.

I only have one computer that can run all this newfangled WebGL stuff at decent speed, and it's my gaming PC at home.

Web gl is a small part of the rich internet applications currently being built. I agree that the web is still too early for advanced games.

On the point of older browsers: 1) the trend of % of people using older browsers is going down. Whereas the number of people using modern browsers without flash and/or java is going up (ie iOS mobile).

2) someone with an older browser expects certain parts of the web to be broken. Being broken in IE6 somewhat says "were more modern than you, try again after you upgrade.". I think people who see this are likely to come back at a future date, whereas someone who can't use it bc of flash is unlikely to think their problem will go away in the future.

But the cost of installing Java is spread across several apps. So the cost is negligible over time.

It is like saying, if I build a web-app, the user needs to first install the browser. True, but once installed, other web-apps have a zero cost of installation.

Not exactly. A web browser has to be installed before they start the process. Java has to be installed either at the beginning of the process or during the process.

I.e. the installation point of java is inside of my conversion funnel for some x > 0% of people I am targeting.

Well, plenty of money has gone into the JVM fast to start. Sure, it's fast to run once warm, making it great for servers, but verifying bytecode and running it is still slow. I've seen benchmarks showing that compiling JS is faster than loading equivalent JVM bytecode.

Additionally, the JVM security model has a much larger surface area than JS, allowing for all kinds of things JS doesn't, which, I'm going to guess is why security has been worse.

Agreed with most points, largely it is timing (as with Flash's original stronghold and the re-up when it solved a huge video on the web problem with Flash video i.e. Youtube rush).

However Snap.svg (snapsvg.io) made by the Raphael creator and backed by Adobe seems to be the best vector animation replacement yet. It is really a mashup of Flash vector and Silverlight declarative style, almost an iteration (you still lose the compiled nature of it and very good compression by default though as it isn't swf -- just like Silverlight). Still nothing has all the features of flash except maybe Unity, minus the vector part, but plugins are looked at in a worse light now.

So we are in this transitionary stage where the new stuff is better but it takes much more work to get it to do the same across all platforms. WebGL, hardware accelerated <canvas> and <svg> and libs that glue those nicely like Three.js or 2D EaselJS and vector libs like Snapsvg will see it through, or further iterations of those. Once WebGL takes hold across all browsers and a couple years we will be in new, more capable hardware accelerated lands. Flash was a big software rendering, CPU hogging bummer at the end.

Snap.svg looks really nice! I meant mainly the Flash authoring tools (Macromedia Flash) are missing. Every idiot used to be able to click together a little animation. It even spawned a new (although questionable) art style of "Flash cartoons".

Let java die in the browser. I'm an advocate for java as a backend language. It's one of the most mature runtimes and for speed and what is great as a server language that doesn't require manual memory management. Hadoop and co is built on top of the JVM for a reason. It's even great as an ecosystem for scala, clojure and all that, but the java GUI tools (swing and I'd even argue fx) are horrible to code with. I won't comment on android as it's a separate beast in that arena.

Java in the browser is an abomination though. As a client side language...forget it. I love it as a server runtime though.

Instead of the JVM-as-moral-equivalent-to-an-embedded-iframe architecture we ended up with, we certainly could have had <script type="text/java">. Or <script type="application/jvm" src="foo.jar">, for that matter, with a JVM "engine" sitting sibling to the position Javascript "engines" have in the browser, in terms of access to the DOM and sandboxing provided by the browser-as-platform. That would have made JVM bytecode a wonderful target.

There actually is a Java DOM API that could have been used in applets. It was never widely supported though, AFAIK.


Asm.js is not Javascript. It's native code!

It's not a VM bytecode. It's assembly language, and the target machine is your native CPU. It is sandboxed by the browser. It is present on any computer with a browser and Javascript, which is more computers than have a browser and Java plugin, or any other plugin for that matter. Asm.js is less mature that Java, but it will grow up. It is currently supported by more browsers than Java, so even if it's crappier right now, it will eventually surpass and replace Java in the browser.

If you are thinking that asm.js is Javascript or is interpreted, you're thinking about it wrong. Think about it this way: Take an arbitrary executable. If you dissassemble it, you have some sort of assembly code. There are several different assembly language syntaxes, but they're all basically the same. Asm.js is basically just another assembly language, with two key differences.

The first difference between asm.js and any other assembly languages is that the only existing asm.js assemblers happen to assemble executables that are sandboxed by your browser. You can't do syscalls to use sockets or files or the Windows registry. You can't fork() or run non-asm.js executables. Still, if you can live with the "syscalls" that the browser gives you, you can run native code in any browser. The browser is your operating system.

The second difference between asm.js and other assembly languages is the really clever part! It is not just assembly. It is both valid assembly language that can be assembled to native machine code and also valid Javascript that can be executed by a Javascript VM -- and both ways of looking at it are semantically equivalent!

It's like being able to write a novel where the text is both valid English and valid Spanish at the same time, and the plot is the same no matter which language you speak.

So I lied. It is Javascript. But you shouldn't think of it that way. You write Javascript. Your compiler writes assembly language. Asm.js is assembly. The Javascript aspect is just a clever backwards compatibility hack. It could have been specified to have a more traditional and readable assembly language syntax, but then you'd need plugins and nobody reads assembly anyway. As is, it's machine code that happens to be able to run on any Javascript VM. This means you can deploy native machine code to any browser without a plugin. In the event that your browser is old and doesn't contain an asm.js assembler, that's ok! Your unmodified native code will still run, albeit more slowly, in a plain old Javascript VM such as everybody has had for years. Except lynx users.

The browser as an operating system is currently worse than a Java runtime plugin in that the browser has less functionality. However, browsers are currently better in that they have more penetration and a higher velocity of improvement. Long term, the browser as a full-featured operating system makes more sense than as a mere scriptable document viewer slash plugin container.

It's assembly language the same way LLVM bitcode is assembly langauge, which means IT ISN'T. It is also represented in text, which means that it is several times larger than it needs to be.

Another problem with Asm.js in practice is that it's used with Emscripten which doesn't define the syscalls you talk about. All the DOM/WebAudio/WebRTC/etc API's have to be redone in Emscripten's headers. GL was easy, because WebGL is so close to EGL and friends. But what about DOM manipulation? Emscripten can't really do this yet.

These two disadvantages happen to be problems solved in PNaCl, which has a compact bitcode (which doesn't pretend to be JavaScript) and a proper API (Pepper).

You are technically correct - the best kind of correct! While I was being a bit loose with my language, I don't think that changes the point.

So maybe it's not an assembly language or a bytecode, but that's a pretty unimportant distinction. Those are all intermediate representations (IR). A good browser will JIT your asm.js IR to machine code in much the same way that a good JVM will JIT your bytecode. An old browser will interpret it more slowly, but it will still work.

Asm.js may be crappy at the moment, but it will get better. It's an easily JITtable IR for the web that's already supported in all browsers, even the old ones. And the security is basically free since that's already being paid for. Yes, it's a bloated text encoding, but gzip is pretty effective. No, it doesn't have great compiler support yet, but Emscripten and equivalent will no doubt have lots of useful headers and emulation and translation libraries very soon. Asm.js is going to win for the same reason that Javascript won: everybody already has it.

Nitpick: asm.js is designed for AOT, not JIT, compilation.

A good browser will AOT asm.js, not JIT it.

(In other words: pre-compiled, not compiled on the fly. Consequence: immediately as fast as a JIT would have… eventually… made it, but initial pause while compiling.)

The fact that asm.js is represented in text does not make it unlike assembly language. It makes it unlike bit/bytecode or machine code.

assembly is just mnemonics for the machine code - that is very important to remember. its a different encoding, but its one which has a strong and tightly coupled relationship to the point where disassemblers are a thing..

sure asm.js is encoded as text, but its not encoding anything close to what assembly languages do.

I have another reply to that effect somewhere in this thread :)

Modern assembly languages often at a slightly higher level of representation than 1-to-1 with the instruction set so it's tough to draw a tough line, but yes, generally speaking, you should be able to translate the majority of the language to machine code with opcode tables. It's also interesting that machine code isn't even the lowest level representation of machine instructions on many architectures, which internally use microcode to implement architectural instructions.

My point was that LLVM bitcode and asm.js are both intermediate targets, but not exactly the same.

You mean macro assembler languages? Its a pedantic distinction but I wasn't intending to imply those... 'Pure' assembly languages are still not 1 to 1 but are never worse than many to one, eg nop is often a real, but useless instruction with some other mnemonic....

Not sure what you point is about microcode... That is an implementation detail which, even for eg, x86 LEA where you think you are leveraging it, it is not important or useful beyond trying to understand performance characteristics. What you get to work with is whole instructions.

We agree! I'm not arguing with you. I'm just trying to provide a bit more context for people who are trying to understand the purpose of all this. Judging by the vast majority of remarks on the article, there's a lot of misunderstanding of how this stuff works.

> It is also represented in text, which means that it is several times larger than it needs to be.

According to the emscripten FAQ[1], gzipped emscriptem output (which uses asm.js) is about the same size as gzipped native code.

[1] https://github.com/kripken/emscripten/wiki/FAQ

Asm.js is not at all an assembly language. An assembly language has a very close, if not one-to-one relationship to actual machine instructions. Assembly language is by definition tied to a particular architecture and non-portable. I've never heard of an assembly language that doesn't let you directly address architectural registers and memory.

Asm.js is just a subset of JS that, when used in blocks, is precompiled. In that sense, it's much more like writing C than assembly (or at least C-like subroutines to be embedded in larger scripts).

Outstanding explanation, +1 and thanks for blowing my mind. I find myself sorely tempted to drop everything and throw myself into this exciting new world. One thing that always bothers me with these xyz.js technologies; Is there an explicit or implicit implication that they are actually implemented wholly or partially in an actual file called xyz.js ? In the particular rather than the general; Is there actually an important javascript source code file involved called asm.js ?

No, asm.js is a subset of JavaScript. So it makes no sense to imagine a single file.

If asm.js is not VM bytecode, what is?

If asm.js is "native code," then what an example of VM bytecode that is not "native"?

I think your point is "all VM bytecodes are not native".

native means the 'byte code' of your hardware... not some VM?

From what I understand, asm.js is using JavaScript as a kind of portable assembly language which means there is no VM.

No VM? What do you call V8, SpiderMonkey, etc?

The conversion from asm.js to native code is much easier than the conversion from JavaScript to native code. The conversion from the real assembly code to native code would be slightly easier than that, but not significantly, making asm.js close to the assembly language (with an infinite number of registers, if that's your concern).

If "ease of converting to native code" is your criterion for "close to assembly language," then Brainf*ck is about the closest to assembly language you can get, because you can write a BF->x86 JIT in about 100 lines of C: http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-s...

So if that's what we're going for, we should forget asm.js and PNaCl and just use BF and expect very close to native speed.

But this won't in fact give native code speed, despite how easy BF is to JIT. Why do you suppose that is?

Huh, I thought it is obvious from the context but I'll restate my words here: It is easier to make native codes from asm.js code than to make native code with the similar performance characteristics from JavaScript code.

It is always easy to get things just work, even while it may mean that printing "Hello, world!" would take minutes. But it is hard to get things work and fast, and there is a certain threshold that it is much harder to optimize once that threshold has been reached. Asm.js have much higher threshold than JavaScript's (and obviously BF's); you can literally replace each line of the already-verified asm.js code with a direct translation with a simple register allocator and it may occasionally (not always, of course) beat optimized JavaScript implementations. Yes, modern JavaScript implementations can optimize the same JavaScript code to that level once it becomes a hotspot! But having a higher threshold changes the problem, for example, time spent to analyze and annotate JavaScript code with hidden types and guards and assumptions can now spent for other optimization passes (e.g. auto-vectorizations).

And you are seriously wrong with BF JIT, you at least have to merge runs of same instructions. (Not to mention other common optimizations, c2bf has only some of them.) Of course it would only matter if you want BF to be fast...

Ah, see, your statements are getting weaker and more qualified, which is what I've been trying to point out.

The original claim in this thread was that asm.js "is native code." This annoyed me in the same way it would annoy an astronomer if you called an asteroid a planet through some chain of tortured logic.

Then OP and others started saying it's "basically the same as native code" because it's "very easy to JIT," but that's clearly not true either thanks to the BF comparison.

So now you're further qualifying by saying ask.js is close to native code because it's easy to JIT "with similar performance." But if I point out corner cases where native code is much faster because of vectorization or use of specialized instructions, you will have to qualify further.

All I am pointing out is that calling asm.js "native code" is inaccurate and misleading. Especially when this is used to imply that asm.js (or PNaCl for that matter) is the be-all end-all answer to giving native code performance. Sure it's a lot closer to native than JS is, but it's still pretty far from actually being native.

> This annoyed me in the same way it would annoy an astronomer if you called an asteroid a planet through some chain of tortured logic.

I think many people just say "stars" while they should say "planets", "asteroids", "stars", "galaxies" etc instead, even when they are well aware that stars are not same as other planetary objects. Well, I think I have made many required qualifications in the second comment as your point becomes clearer. (And I think many others have the similar assumptions, but that's another story.)

> All I am pointing out is that calling asm.js "native code" is inaccurate and misleading.

You are totally right on that. Asm.js is just "a JavaScript subset that can act like a portable assembly language". No performance guarantee here. One can expect the performance boost with the reasonable assumptions but as far as I recall V8 people don't think so. In fact, I'm not that interested in the performance of asm.js but in the potential use of asm.js for non-JS contexts.

Browsers are supposed to compile asm.js code directly into native code before running it. Running it through the VM is the fallback for browsers that don't support it directly.

I can compile BF directly to native code (and actually I did: http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-s...) so does that make BF native code?

The point of these questions is that the GGP's statements are absurd. There is no universe in which asm.js is "native code".

No, it's not technically native code, nor is it exactly assembly or bytecode. It an IR that browsers can JIT very easily. Which is basically the same thing.

It's interesting to note that x86 and amd64 code isn't even truly "native". They're just bytecode IRs that are interpreted by a CISC virtual machine emulated in microcode running on a RISC cpu that you can't program directly. Everything is an IR. Python is an IR for the thoughts in my head. It's turtles all the way down.

> No, it's not technically native code, nor is it exactly assembly or bytecode. It an IR that browsers can JIT very easily. Which is basically the same thing.

So BF is "basically" native code too, since it can be JITted very easily? In fact, it's much easier to JIT BF than asm.js, so according to your definition it is even more "native" than asm.js.

The way you are using "native" takes away all of its meaning.

> Everything is an IR. Python is an IR for the thoughts in my head. It's turtles all the way down.

It's really not.

Yes, every executable representation is a representation (though we don't usually call representations "intermediate" if they are designed to be executed directly).

But the hand-wavy idea that because two things are both representations they are "basically the same thing" is so far from true that it is the opposite of insight. The truth is that the differences between representations is one of the deepest concepts in compilers and VMs.

For example, the entire difference between asm.js and PNaCl mostly boils down to the differences between their two different representations (a modified LLVM bitcode vs. a JavaScript subset). If these two things are "basically the same" then asm.js and PNaCl are "basically the same" too.

True but I'm replying to a comment stream that describes asm.js code as "portable assembly language" which is a pretty reasonable description.

It's certainly not native code since no CPU exists that can execute asm.js code directly.

Java's greatest sin for the web was not having the JVM have access to the DOM like javascript.

The web's greatest sin was allowing programmatic access to the DOM, IMO.

Interactive sites suck, if you want that, use a sandbox so I can easily discard it.

I always have issue with the idea that a JIT or interpreter can rival native code.

In many cases it just reveals a lack of understanding of why C is powerful. It lets you choose your implementation details very heavily (not heavily enough imo [!]) to the point where few languages can do things it can't. Meaning that comparing like for like code is naive - you should compare a copy of the 'faster' implementation in C to the implementation in the language being benchmarked. Due to design limitations its basically impossible for Java to seriously compete with C...

I do generally agree that Java gets a serious bad rap for nearly nothing though...

I can fully recognize that Java is a fast and powerful language, but it also makes me want to shove huge wooden slivers up my fingernails. That doesn't change despite the truth of your statements.

But what the poster is really thinking of is the JVM. We now have Scala, Clojure, and others that target the JVM as a platform.

The JVM doesn't run on Android or iOS, and never will. That's a huge chunk of users they can't touch, but the web can.

Aren't all Android apps running the JVM?

They run Dalvik, which is Googles proprietary VM. Its similar to the JVM in purpose, but it is supposed to avoid Oracle's patents and has a few specializations for mobile.

AFAIK (I'm not a java developer), any language that can target the JVM can target Dalvik.

AFAIK, the only language that's officially supported by Dalvik is Java, and code in other languages tends to run into limitations in the bytecode-to-Dalvik translator.

Surely there is a Scala for it? Alternatively use Mono and C#/F#.

The issue is not any particular language but the platforms. Asm.js is an assembly language that gives native-code performance to browsers that's theoretically on-par with the JVMs' JITs.

You can think of asm.js as a bytecode (like JVM bytecode) that all browsers can interpret. Some browsers are now getting JITs for this "bytecode".

You don't write asm.js in the same way that you don't write assembly or JVM bytecode by hand. You write Java or Clojure or Scala or C or Haskell. Your compiler then turns that into either JVM bytecodes or asm.js assembly. And your JVM or browser will JIT that bytecode into native code.

The real issue now is that the JVM is currently a more capable platform, but the browser has broader penetration and arguably better security. Raw performance is becoming a non-issue with asm.js.

Actually asm.js is possible to AOT compile, not just JIT.

On a related note, are there anything preventing a language like Clojure(script) that already targets the browser to target asm.js instead? What would the advantages and disadvantages be (if any)?

I'm pretty sure the same argument can be made, but more strongly, for C.

C is massively more cross platform than Java - a JVM implementation often relies on C. C compilers are often the first things implemented for new platforms. C is very close to pure native code - to the point where many equate C/C++ with native. All of Java can be beaten or matched by C performance wise because of the power it gives to leverage the hardware in precisely the same way the JVM can but without (so many) overheads that are designed in.

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