6 ms·
Asm.js: A Low Level, Highly Optimizable Subset of JavaScript for Compilers
- fijal 14y agox | 0 as declaring int. +x as declaring float. Math.imul to multiply integers. seriously???!!! It took me roughly half an hour to decide whether it's an elaborate joke or an actual idea. Also javascript (without introducing new concepts) is not low level enough to write down everything you might need (have fun implementing 64bit integer operations with overflow for example).
- devongovett 14y agoWell luckily you don't have to write it. Use a compiler that can generate it for you. It's not really designed for humans.
- fijal 14y agoIt's a very bad target for compilers too. Guys should just get their stuff together and write a reasonable bytecode format for browsers that is fast to read and verify. Would also save quite a bit of transfer. PS. If intel told me to do such crap in their architecture manuals, I would be the last user of PPC out there. I suggest reading them, or JVM bytecode spec to see what is a good compiler target.
- devongovett 14y agoYeah, that's the position of Google's NativeClient project. But it's not backwards compatible with older browsers, which is the reason for doing this how they are. asm.js will run in any browser supporting JS already, and will be faster in browsers supporting the optimizations. It's not perfect, but it works now.
- deleted 14y ago[deleted]
- hermanhermitage 14y agoWhats your metric for "bad"? It seems like complaining about ELF format or the different assembly formats used by assemblers. Ok, there is no goto/jmp but apart from that its just a different assembly syntax which happens to also support expressions and not just diadic/triadic instructions. This is not a green field solution - which would require alignment from all browser vendors, but instead an attempt to explore within the confines of what already runs today.
- adamnemecek 14y agoWhen I was making a very argument in the last thread, it seemed like people for whatever reason just did not want to let JS go.
- chc 14y agoYou're mistaken. It is not that people "just did not want to let JS go," but that "let JS go" is so immensely hard at this point in time that it is sitting near "boil the ocean" on the practicality scale. We don't know how to do it, so it's not a meaningful suggestion. In order to convince people that it's even worth trying, you need to enunciate a) a practical plan for "letting JS go," and b) a case for why the advantages of that plan in the context of the modern browser landscape outweigh the advantages of the plan the Mozilla devs are going with. You didn't do that. To put it another way: If we were implementing Web browser scripting completely from scratch with no history to lean on, this is not how I would do it and probably not how Dave Herman would do it either. But we aren't in that situation. As it stands, there are lots of existing JavaScript implementations that browser makers are heavily invested in — and they are not going to throw that all out and implement a new, incompatible and much more restrictive standard just because I wave my magic wand. The idea behind asm.js is that it is the smallest change you can make to still get the desired effect, because change is hard. Even if you don't think asm.js is perfect, it's a huge step in the direction you want to go. Complaining that it doesn't teleport us all the way there seems like missing the point.
- adamnemecek 14y agoI mean I get it but not acknowledging that sometime in the future, the band-aid will have to be torn off, and not talking about what would is the best way to do so is not helping either.
- chc 14y agoSure, that would be an interesting conversation to have. But that's not what anyone's doing. Complaining that asm.js piggybacks off JavaScript instead of being a bytecode for which no interpreters currently exist — which is what you and fijal seem to be doing — is not "talking about what would be the best way to do that." In case you've forgotten, your suggestion in the other thread was literally just "a standardized VM in the browser." When I tried to get you to elaborate on what that meant in practical terms, you couldn't explain how it would be any different from what we have with asm.js except that you want a bytecode syntax for the input instead of the syntax asm.js uses. If you want to talk about practical ways we might move beyond JavaScript someday, feel free. I think that's an interesting topic. That's why I think it's unfortunate that so far, people just seem to be complaining that asm.js doesn't involve bytecode. Personally, I think asm.js is an important step in the direction of a post-JavaScript world. It moves us away from dependence on JavaScript by helping to better enable alternative languages in the browser.
- chc 14y agoYou are overstating your case. It is not ideal, but it is serviceable. It is most importantly better than what we have now. To call an indisputable improvement "very bad" pretty much strips the word "bad" of all meaning.
- pcwalton 14y ago"It's a very bad target for compilers too." Emscripten is nowhere near the complexity of a SelectionDAG-based LLVM backend. In fact Emscripten is mostly written in JavaScript. The only comparatively tricky part is the Relooper, which is just a few pages of code. "Guys should just get their stuff together and write a reasonable bytecode format for browsers that is fast to read and verify." A nice-looking bytecode doesn't seem worth the loss of backwards compatibility. The encoding is ugly, but compatibility with existing browsers seems like such a huge win for something that really just amounts to a different encoding. "Would also save quite a bit of transfer." The effect on download size is minimal actually, compared to native code. And compared to gzipped LLVM bitcode, gzipped asm.js is tiny. http://mozakai.blogspot.com/2011/11/code-size-when-compiling-to-javascript.html http://mozakai.blogspot.com/2011/11/code-size-when-compiling...
- skatepark 14y ago> A nice-looking bytecode doesn't seem worth the loss of backwards compatibility. The encoding is ugly, but compatibility with existing browsers seems like such a huge win for something that really just amounts to a different encoding. 10x slowdown doesn't seem worth keeping backwards compatibility. Why even bother? 2x in the best case is more reasonable, but wouldn't a 1x best case (NaCL) be even better, if you're willing to actually drop backwards compatibility?
- sultezdukes 14y agoBecause "guys" can't. The browser world is laden with massive backward compatibility issues that will never, ever go away. Yeah, I would love something like NaCL, but that aint' happening, so baby steps.
- fijal 14y agoIt's actually very likely I have to write it. I write compilers. Hence the hatred. I would seriously choose x86 ASM with all the backwards compatibility quirks going back to 80s any day.
- pcwalton 14y agoWell, if you're interested in compiling to something that runs in all browsers, you have to compile to JavaScript anyway. Given that, asm.js is strictly an improvement over the current state of affairs: the rails to stay on for high performance are well defined and (hopefully eventually) cross-browser. The alternative is to try to make a clean break from the past and forego backwards compatibility in the name of a cleaner encoding, so that compiler authors can generate object files with nicer syntax. That sort of thing been tried many times in the history of the Web and usually hasn't ended up succeeding. For example, take XHTML 2: despite the fact that XHTML 2 was hugely cleaner than HTML 4/XHTML 1, it never got any traction and was abandoned by the W3C. At the scale of the Web, practical considerations end up dominating engineering considerations.
- azakai 14y ago> x | 0 as declaring int. +x as declaring float. Math.imul to multiply integers. seriously???!!! |0, + etc. are how compilers to JavaScript - emscripten, mandreel, others - have been implementing integers and so forth for years. The bitwise operators and + have the right semantics for that, and are concise. So these are not ways to "declare" integers - they are functional syntax, things that actually do something. In the asm.js type system, it was therefore natural to use them to also "declare" types. But only in the sense that asm.js figures out the types exactly as JS engines do, from code that has actual effects. (Compare to closure compiler type annotations, which are arbitrary and have no effects.) Math.imul is not strictly necessary, but it fixes a specific pain point in JS (that multiplying large integers can be rounded due to JS numbers being doubles). You can use asm.js without it though, might be some slowdown with large ints but not large. asm.js is perfectly viable without Math.imul. Besides all this though, the important bit to remember is that this is a compiler output. It's not a human-readable language. It doesn't matter if multiplication is * or DO_MUL or anything else, just like it doesn't matter how multiplication commands look (in terms of binary data) in x86 or ARM machine code. > Also javascript (without introducing new concepts) is not low level enough to write down everything you might need (have fun implementing 64bit integer operations with overflow for example). Depends on what you need. Current asm.js can run Sauerbraten, a 100 KLOC complete game engine with physics, AI, rendering, world geometry system, scripting language - not JS! :) - , level file formats etc etc. It is also enough to run large projects like Python, Bullet, etc. So it already supports quite a lot. In fact almost the entire emscripten test suite runs as asm.js, and that's a lot of C/C++ code. But yes, there are some areas that are trickier, like true 64-bit ints.
- fijal 14y ago| Depends on what you need. Current asm.js can run Sauerbraten, a 100 KLOC complete game engine with physics, AI, rendering, world geometry system, scripting language - not JS! :) - , level file formats etc etc. It is also enough to run large projects like Python, Bullet, etc. So it already supports quite a lot. In fact almost the entire emscripten test suite runs as asm.js, and that's a lot of C/C++ code. well, yes, computers got a lot faster. I just wish the software stop getting slower at a similar or faster pace. The fact that I have to buy a new computer to play 8-bit games that were available on DOS and run fine on 386 is kind of ridiculous (but hey, they're over the internet).
- niggler 14y agox|0 is a standard idiom, as explained in the ECMAScript Spec: The production A : A @ B, where @ is one of the bitwise operators in the productions above, is evaluated as follows: - Let lref be the result of evaluating A. - Let lval be GetValue(lref). - Let rref be the result of evaluating B. - Let rval be GetValue(rref). - Let lnum be ToInt32(lval).* <-- Convert to 32 bit Integer - Let rnum be ToInt32(rval).* - Return the result of applying the bitwise operator @ to lnum and rnum. The result is a signed 32 bit integer. x|0 is therefore the result of ToInt32(x), which is effectively a coercion to integer. Directed link to the section in the annotated spec: http://es5.github.com/#x11.10 http://es5.github.com/#x11.10 (or http://ecma-international.org/ecma-262/5.1/#sec-11.10 http://ecma-international.org/ecma-262/5.1/#sec-11.10 -- as evilpie pointed out in a reply) For the original spec, read Pages 82-83 of http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf http://www.ecma-international.org/publications/files/ECMA-ST...
- evilpie 14y agoAs of a few months ECMA now hosts their own html version of the spec. http://ecma-international.org/ecma-262/5.1/#sec-11.10 http://ecma-international.org/ecma-262/5.1/#sec-11.10
- kibwen 14y agoPrior discussion (with comments from dherman, Luke Wagner, and various other Mozilla employees): http://news.ycombinator.com/item?id=5227274 http://news.ycombinator.com/item?id=5227274
- mistercow 14y agoI get the point of Math.imul, but it seems at odds with the idea of asm.js being backward compatible. I guess it's easy enough to provide a polyfill (MDN even provides one), but that seems rather inelegant.
- azakai 14y agoIt's a pretty minor issue - asm.js is viable without it. For multiplications of small numbers, like 5 times x where x is 32-bit, you don't need Math.imul, normal multiply is fine. The only case where Math.imul is useful is x times y where neither x nor y is known at compile-time, so in theory they could be big enough to cause double-rounding in JS. But even in that case, emscripten can emit code without Math.imul (there is a compiler flag). The code will work, but is a little slower than Math.imul, that's all. In fact in practice you don't even need the polyfill on MDN (which is precise), you can do imprecise multiplication with double-rounding, that works in 99% of cases in my experience, making Math.imul even less crucial. But it's nice to have Math.imul, just to say that even in the worst case (odd codebase with tons of integer multiplies that are very often of integers both very very large), performance will be predictable and fast.
- haberman 14y agoAs someone who's been a vigorous proponent of (P)NaCl for a long time, I have to say that I'm excited to see this. If it can truly deliver on its promise (near-native-code speeds with no imposed GC overhead), it will be a truly welcome advance indeed. I hope that if it does succeed that it will open up even more possibilities, like optional SSE/AVX intrinsics (for added speed in the most demanding software) and threading support. It's great and educational to see an alternative approach to the problem that is obviously quite different than (P)NaCl. May the best technology win.
- gsnedders 14y agoFor much, NaCl has a 2x perf penalty (v. native C++), and PNaCl higher (compilation overhead, and compilation has a higher cost: delaying runtime from starting). asm.js already, despite being brand-new, for much has a 2x perf penalty: equal with NaCl, yet more portable. (See zlib, for an example of this.) There are still cases where asm.js is slower (box2d, for example, though there it's broken JS through the point needed for 60fps), but I'd expect nothing but the difference to decrease. Unlike PNaCl, it's not mere research (after several years it's still not shipped), works cross-browser, and further unlike NaCl, works cross-platform. I expect someone will write some binary serialization for asm.js: you have all the primitives for iadd, isub, etc.
- haberman 14y ago> For much, NaCl has a 2x perf penalty (v. native C++) Huh? From the NaCl paper: "The worst case performance overhead is crafty at about 12%, with other benchmarks averaging about 5% overall." How do you get from 5% to 2x (100%)? > asm.js already, despite being brand-new, for much has a 2x perf penalty: equal with NaCl Have you actually run the same benchmarks on both and found them equal? According to this comment no such benchmarks have been performed yet (at least by azakai): http://news.ycombinator.com/item?id=5228737 http://news.ycombinator.com/item?id=5228737 If not, declaring it "equal" seems a bit premature.
- comex 14y agoJust to inject another viewpoint into this - I don't care that asm.js is backward compatible with JavaScript. If my program uses an appreciable fraction of the available CPU an it has to act real time in some fashion (anywhere from 60fps for a game to simply acting responsive in a GUI app), execution several times slower by a standard JS VM is no better than no execution. If I want to be cross-platform in the hopefully near future where asm.js is not widely supported, I would pick Chrome and Firefox to support for now and use a NaCl plugin for the former. From this perspective, a "true" bytecode VM would be no worse - and it would hardly be boiling the ocean, since the size of code required to parse a simple bytecode is negligible. (If you want to compile it efficiently, either you bring in all of LLVM or modify your JS engine, which is hardly negligible, but asm.js is the same in that regard. The only difference is parsing.) But I think it's nice that the "bytecode" is human readable and pretty much writable. It will be better to use a (possibly lightweight) too to compile to asm.js, but it's nice that small kernels can just be written without a compiler.
- Arelius 14y ago> execution several times slower by a standard JS VM is no better than no execution Having worked in games for a while I disagree. From a user perspective, I've found that when games don't work at all players often feel the developer is too blame, while if it runs but just unplayable slow they are much more open to blame the system they play it on. And let's be honest, if this is important for any sort of app, games are indeed one of them. Additionally, I'd much rather all my features work, but have to scale back on visual effects, rather than have to write both a high-performance, and a low-performance version, and still be required to scale back effects. From my perspective in game development the asm.js approach seems to be a significant win.
- yareally 14y ago> Having worked in games for a while I disagree. From a user perspective, I've found that when games don't work at all players often feel the developer is too blame, while if it runs but just unplayable slow they are much more open to blame the system they play it on. Steam comments on their forums seem to blame developers regardless from just my history of reading them. There might be more arguments about who is to blame (when there's some it runs fine for), but plenty still blame the developer when it runs slow and their system should be able to run it (such as in claims x similar game runs so y should [even if it's not apples and oranges, but users think so anyways]).
- javajosh 14y agoCan coffeescript generate asm.js compatible javascript? Or rather, what changes to coffeescript would be required to support it, I wonder?
- dangoor 14y agoCoffeeScript and JavaScript are semantically almost the same. CoffeeScript is not going to magically become faster because of asm.js. As I understand it, asm.js is really intended as a compiler target for languages with different semantics from JS that can achieve better performance by hinting more directly about what the machine should do.
- javajosh 14y agoAh, I see. That's why GWT would really benefit from asm.js but coffeescript would not: the Java-source already contains the extra type information (that is currently being mostly ignored), whereas Coffeescript is just as dynamic as native JavaScript. Not sure why I got downvoted for asking though. Oh well! Cheers.
- azakai 14y agoIt would need types, basically. That would be a big change for CoffeeScript, and doesn't feel like what the language is aiming for, so probably not relevant I suspect.
- justin_vanw 14y agoWhy would we go this route? Why not just define a bytecode spec and be done with all of this nonsense? Mozilla is perfectly free to implement the bytecode by compiling it to a restricted subset of JS (in fact, it might make a lot of sense to do so). Defining a simple register or stack based machine and producing bytecode for it would greatly simplify the job of implementers, it would make defining the specification and determining compliance with the standard very straight forward, and it would let us eventually do web programming without being tied to a specific language.
- azakai 14y agoWhy would a bytecode spec be simpler for implementers? Is there some part of the spec of asm.js that looks hard to implement to you? And why would a bytecode spec be better for other languages than this approach (which also supports that)?
- justin_vanw 14y agoI don't know you, but I'm guessing you are somehow in love with javascript and invested in seeing it succeed. The world is largely divided into two camps, the people who are in love with javascript and the people who think it is a sick joke. Those of us in the 'sick joke' camp would like to see javascript made optional to web programming, and not a part of our toolchain at all. If javascript is part of the toolchain at all, I will have to eventually debug javascript code, and javascript was written under the 'principle of maximum surprise' making it a very awful language to those of us who haven't based our careers on learning every single edge case (and every case is an edge case in javascript!) The other half of the world is the 'javascript is great' people, and they usually learned to program with javascript or have spent a large portion of their coding career inside of it. They don't see what the big deal is, it's a perfectly good language, right? Well, it's actually a pretty gross language that has one amazing feature, it is available on every computer without having to install anything extra. Please, let us have the OPTION of a completely javascript free web. The javascript fans can keep it, just give the rest us a choice.
- 14y ago