18 ms·
Towards a JavaScript Binary AST
- bigato 9y agoTrying to catch up with webassembly, huh?
- dmitriid 9y ago> By design, however, wasm is limited to native code, so it doesn’t work with JavaScript out of the box. By design of the first MVP iteration. http://webassembly.org/roadmap/ http://webassembly.org/roadmap/ and http://webassembly.org/docs/future-features/ http://webassembly.org/docs/future-features/ GC (which is the main major feature required for JavaScript) is in progress, https://github.com/WebAssembly/design/issues/1079 https://github.com/WebAssembly/design/issues/1079 So, your article is FUD in it's purest undistilled form.
- kuschku 9y ago> So, your article is FUD in it's purest undistilled form. The article is just reiterating an argument that Mozilla and Facebook made. If you’re saying Mozilla and Facebook are spreading Fear Uncertainty and Doubt with their proposal for a binary JS AST, then you may do so, but please realize that they probably had good reasons to start such a project. EDIT: Even though I disagree with the parent, it is making some good points (specifically, that WebASM is going to add a GC), so flagging it to death doesn’t seem to be the right thing to do.
- dmitriid 9y ago"If big boys do it, it must be right" is a feeble argument
- lllr_finger 9y agoYou're obviously passionate about this; I'd personally be interested in seeing some more concrete points detailing exactly why this is bad.
- dmitriid 9y agoHere: https://news.ycombinator.com/item?id=15045697 https://news.ycombinator.com/item?id=15045697 I'd like to see why it is good, given efforts with WebAsembly
- wiremine 9y agoI haven't tracked WASM closely, so this is an honest question. Are you saying this comment is false? > I am not aware of any project that achieves compilation of JavaScript to wasm I.e., Javascript to WASM is on the roadmap and something we can use in the next few years? Or am I misunderstanding the situation?
- dmitriid 9y agoI'm saying that the whole idea of this project is built on top of false assumptions, and any counterarguments are dismissed.
- Yoric 9y agoYes, dmitriid, I believe it's clear by now that you don't like this project. As I mentioned in another conversation, if you feel you can contribute to Wasm and make it solve the problems we are solving here, this is great, by all means, please do so. In the meantime, we are going to continue trying to solve some of the performance problems of the web using the techniques discussed in the blog entry because we are convinced that they are going to work better.
- dmitriid 9y agoI find zero arguments in your comment except ad hominem attacks.
- ryanong 9y agoThis is some amazing progress, but reading this and hearing how difficult JavaScript is as a language to design around makes me wonder how many hours have we spent optimizing a language designed in 2 weeks and living with those consequences. I wish we could version our JavaScript within a tag somehow so we could slowly deprecate code. I guess that would mean though browsers would have to support two languages that would suck..... this really is unfortunately the path of least resistance. (I understand I could use elm, cjs, emscriptem or any other transpirer but I was thinking of ours spent around improving the js vm.
- exikyut 9y ago> I wish we could version our JavaScript within a tag somehow Behold one of the implementational details that emerged out of this language that was indeed "designed in 2 weeks": <script type="text/javascript1.0">...</script> <script type="text/javascript1.1">...</script> <script type="text/javascript1.2">...</script> <script type="text/javascript1.3">...</script> <script type="text/javascript1.4">...</script> <script type="text/javascript1.5">...</script> https://tools.ietf.org/html/rfc4329 https://tools.ietf.org/html/rfc4329: 3. Deployed Scripting Media Types and Compatibility Various unregistered media types have been used in an ad-hoc fashion to label and exchange programs written in ECMAScript and JavaScript. These include: +-----------------------------------------------------+ | text/javascript | text/ecmascript | | text/javascript1.0 | text/javascript1.1 | | text/javascript1.2 | text/javascript1.3 | | text/javascript1.4 | text/javascript1.5 | | text/jscript | text/livescript | | text/x-javascript | text/x-ecmascript | | application/x-javascript | application/x-ecmascript | | application/javascript | application/ecmascript | +-----------------------------------------------------+ https://www.quirksmode.org/js/intro.html https://www.quirksmode.org/js/intro.html (from circa 2007, when it was trendy to NOT date webpages shakes fist): > JavaScript versions > There have been several formal versions of JavaScript. > 1.0: Netscape 2 > 1.1: Netscape 3 and Explorer 3 (the latter has bad JavaScript support, regardless of its version) > 1.2: Early Version 4 browsers > 1.3: Later Version 4 browsers and Version 5 browsers > 1.4: Not used in browsers, only on Netscape servers > 1.5: Current version. > 2.0: Currently under development by Brendan Eich and others. The link above points to a bit of interesting general discussion about versioning, and isn't as dense as the RFC.
- cabaalis 9y agoSo, compiled Javascript then? "We meet again, at last. The circle is now complete." The more I see interpreted languages being compiled for speed purposes, and compiled languages being interpreted for ease-of-use purposes, desktop applications becoming subscription web applications (remember mainframe programs? ), and then web applications becoming desktop applications (electron) the more I realize that computing is closer to clothing fads than anything else. Can't wait to pickup some bellbottoms at my local target.
- Yoric 9y agoWell, it's more "compressed JavaScript" than "compiled JavaScript".
- dmitriid 9y agoIt's not. It's a binary representation of JS. Basically directly competing with WebAssembly. What happens a year from now when WebAssembl gets support for GC and modules?
- Yoric 9y agoPlease don't tell me what the project is, I'm the tech lead :)
- dmitriid 9y agoSo why do you dismiss any and all arguments against it? Repeatedly. You and your supporters consistently spread false information. - WebAssembly does not support JS hence we need binary AST WebAssembly is on track to support dynamic and GC-ed languages - WebAssembly will be slower than binary AST You've provided zero support for this statement. Meanwhile experiments with real apps (like Figma) show significant improvements with WebAssembly - No one wants to ship bytecode False - it's hard to align browsers on bytecode See WebAssembly - you can't change bytecode once it's shipped You can, eventually. Same argument can be applied to binary AST - WebAssembly not supported by tools Neither is binary AST. Meanwhile one of the goals of WebAssembly is tool support, readability etc. There were other claims just as easily falsified, and yet dismissed out of hand. So. What are you going to do with JS AST when WebAssembly gets support for JS?
- FrancoisBosun 9y agoI feel like this may become some kind of reimplementation of Java's byte code. We already have a "write once, run anywhere" system. Good luck!
- Yoric 9y agoNot really. The reimplementation of something like Java's bytecode is Wasm. This one is more of a compression format than a bytecode.
- jlebrech 9y agowith an AST you can visualise code in ways other than text, and also reformat code like in go-fmt.
- Yoric 9y agoIndeed. That's not one of the main goals of the project, but I hope that standardizing the AST will help a lot with JS tooling, including code visualisation.
- jlebrech 9y agoI want to see a code editor that represent common programming language concepts such as classes, functions (OO) in a graphical way and displays the rest in text.
- Yoric 9y agoThat would certainly be cool :)
- robertkrahn01 9y agohttp://imgur.com/a/c7cNx http://imgur.com/a/c7cNx
- jlebrech 9y agobit old school, but in that direction. yes
- onion2k 9y agoThis is a really interesting project from a browser technology point of view. It makes me wonder how much code you'd need to be deploying to for this to be useful in a production environment. Admittedly I don't make particularly big applications but I've yet to see parsing the JS code as a problem, even when there's 20MB of libraries included.
- Yoric 9y agoWe're working towards experimenting this. For the moment, benchmarks suggest that this will be noticeable after 1 or 2Mb of code. We'll only know for sure once we can start testing in real conditions, though.
- Yoric 9y agoI should have mentioned "1 or 2Mb of code on an average-ish computer".
- nfriedly 9y agoOn a decently fast computer, you're right. On a low-end cell phone, 20MB of libraries will take a noticeable amount of time to parse.
- kevinb7 9y agoDoes anyone know the actual spec for this binary AST can be found? In particular I'm curious about the format of each node type.
- Yoric 9y agoThe specifications are not nearly stable enough to be publicized yet. In particular, there are several possibilities for file layout, compression, etc. and we have barely started toying with some of them, so any kind of spec we publish at this stage would be deprecated within a few weeks. If you wish to follow the development of the reference implementation, you can find it here: https://github.com/Yoric/binjs-ref/ https://github.com/Yoric/binjs-ref/ . It's very early and the format will change often as we 1/ fix bugs; 2/ remove debugging info; 3/ start working seriously on compression; 4/ optimize.
- le-mark 9y agoHere's some perspective for where this project is coming from: > So, a joint team from Mozilla and Facebook decided to get started working on a novel mechanism that we believe can dramatically improve the speed at which an application can start executing its JavaScript: the Binary AST. I really like the organization of the present article, the author really answered all the questions I had, in an orderly manner. I'll use this format as a template for my own writing. Thanks! Personally, I don't see the appeal for such a thing, and seems unlikely all browsers would implement it. It will be interesting to see how it works out.
- lj3 9y agoAll they have to do is convince Google. Chrome's the king of the castle right now.
- markdog12 9y agoNative Client
- lj3 9y agoFirefox had a much higher market share than Chrome back then. Context matters.
- markdog12 9y agoMozilla and others had pretty strong technical objections to Native Client. Context matters (sometimes :))
- lj3 9y agoOh, I think I misunderstood you. You mean the AST is going to go the way of Native Client because Mozilla doesn't have the muscle it used to? Or do you think Google's going to sandbag it as revenge for Native Client? :)
- nikita2206 9y agoIn this thread: people not understanding the difference between byte code (representing code in the form of instructions) and AST.
- apaprocki 9y agoFrom an alternate "not the web" viewpoint, I am interested in this because we have a desktop application that bootstraps a lot of JS for each view inside the application. There is a non-insignificant chunk of this time spent in parsing and the existing methods that engines expose (V8 in this case) for snapshotting / caching are not ideal. Given the initial reported gains, this could significantly ratchet down the parsing portion of perceived load time and provide a nice boost for such desktop apps. When presented at TC39, many wanted to see a bit more robust / scientific benchmarks to show that the gains were really there.
- Yoric 9y agoYep, working on it.
- kannanvijayan 9y agoYoric is working on a "proper" implementation and I'll be assisting in the design work, and if needs be some implementation. I think the next milestone here is a working demo in Firefox with Facebook page load. At a personal level, I feel pretty confident that BinaryJS will help your case. The theory behind the gains was pretty solid before we designed the prototype. The prototype, for me, basically proved the theory. My personal hope is that by the time we're done squeezing all we can out of this - which includes zero-costing lazy function parsing, and on-line bytecode generation, we can cut the "prepare for execution" time by 80%.
- hashseed 9y agoDo you have any details on what could be improved wrt V8's snapshotting? We have recently extended the feature set a lot in order to be able to snapshot full Blink contexts, and there are some efforts on-going to implement that in Node.js as well. Soon crutches like electron-link won't be necessary anymore. Some context: https://v8project.blogspot.com/2017/05/energizing-atom-with-v8s-custom-start.html https://v8project.blogspot.com/2017/05/energizing-atom-with-... https://github.com/nodejs/node/issues/13877 https://github.com/nodejs/node/issues/13877
- nfriedly 9y agoTo clarify how this is not related to WebAssembly, this is for code written in JavaScript, while WASM is for code written in other languages. It's a fairly simple optimization - it's still JavaScript, just compressed and somewhat pre-parsed. WASM doesn't currently have built-in garbage collection, so to use it to compress/speed up/whatever JavaScript, you would have to compile an entire JavaScript Virtual Machine into WASM, which is almost certainly going to be slower than just running regular JavaScript in the browser's built-in JS engine. (This is true for the time being, anyway. WASM should eventually support GC at which point it might make sense to compile JS to WASM in some cases.)
- Yoric 9y agoLet me add a second emphasis on "might" and "some cases".
- syg 9y agoThis is important, as there seems to be a lot of misunderstanding in this thread. What's proposed is structural compression of JS with JS-specific bits to speed things up even more. What's proposed is not compiled JS, in that the original JS is not meaningfully transformed at all. There is a very explicit design goal to retain the original syntactic structure. OTOH WebAssembly is like a new low-level ISA accessible from web browsers. To use wasm, one does have to compile to it. As the parent here says, compiling JS -> wasm currently requires at least a GC but also much more. To engineer a performant VM and runtime for a dynamic programming language like JS is a time-consuming thing. It is curious to see so many folks think that JS can straightforwardly be compiled to wasm. Currently wasm and JS serve very different needs; and I also don't think JS will be going anywhere for many, many years. Edit: formatting
- sjrd 9y agoThis is a very good point. I would also add that there are a lot of languages compiling to JavaScript that would similarly not benefit from wasm. Right now, pretty much all GC-ed languages compiling to JS (such as ClosureScript, Elm, Scala.js, BuckleScript, PureScript, etc.) are in that category. Even if/when wasm supports GC in the future, I expect that dynamically typed languages compiling to JS will still be a long way from benefiting from wasm. However, all these languages can benefit from the Binary AST right away. Just like any codebase directly written in JavaScript. If the Binary AST has some decent story about position mapping (see [1] which I just filed), they might even get somewhat better tooling/debugging support going through the Binary AST than going through .js source files, out of the box. [1] https://github.com/syg/ecmascript-binary-ast/issues/17 https://github.com/syg/ecmascript-binary-ast/issues/17
- vvanders 9y agoLua has something very similar(bytecode vs AST) via luac for a long while now. We've used to to speed up parse times in the past and it helps a ton in that area.
- Yoric 9y agoI'm interested. Do you have a link?
- vvanders 9y agoYup, from the docs(there's also a little bit describing how it's interpreted in the "load()" main docs as well): https://www.lua.org/manual/5.1/luac.html https://www.lua.org/manual/5.1/luac.html
- spc476 9y agoThere's a problem---you can break out of Lua with malformed bytecode [1] and the Lua team don't want to spend the time trying to validate Lua byte code [2]. That's why the latest Lua version has an option to ignore precompiled Lua scripts. And sadly, I can see the same happening here. [1] https://www.corsix.org/content/malicious-luajit-bytecode https://www.corsix.org/content/malicious-luajit-bytecode [2] The overhead will eat any performance gained by using precompiled Lua code in the first place.
- vvanders 9y agoSure, if you're loading scripts from an untrusted source then don't use bytecode. They're pretty clear about that in the docs. However probably about 90% of Lua's use cases are embedded and so in that case it works just fine.
- agumonkey 9y agohehe, reminds me of emacs byte-compilation..
- Laaas 9y agoWhy does this guy use bits instead of bytes everywhere?
- malts 9y agoYoric - the Binary AST size comparisons in the blog - was the original javascript already minified?
- Yoric 9y agoOn our sample, x0.95 for minified code (so that's a 5% improvement) and ~x0.3 for non-minified code. As usual, read these numbers with a pinch of salt, they are bound to change many times before we are done.
- malts 9y agoDoes BinJS perform AST transforms like `!0` to `true` which would be shorter in binary AST encoding? Or does it faithfully model the original code?
- Yoric 9y agoIt faithfully models the original code. The idea is that if you want to transform `!0` to `true`, or if you want to obfuscate, etc. you can always plug an additional tool.
- malts 9y agoThe 5% gains over minified code are impressive given that BinJS performs no AST manipulation. The BinJS prototype will be written in pure javascript I assume to speed its adoption?
- Yoric 9y agoFor the moment, it's JS + Rust, because Rust is better than JS when you keep refactoring Big Hairy Data Structures. However, once the data structures stabilize we're planning to shift it entirely to JS.
- mnarayan01 9y agoFor those curious about how this would deal with Function.prototype.toSource, via https://github.com/syg/ecmascript-binary-ast#functionprototypetostring https://github.com/syg/ecmascript-binary-ast#functionprototy...: > This method would return something like "[sourceless code]".
- _wmd 9y agoIt seems this would break a number of libraries (can't name one, but certain I've seen it), although per the article it would be a simple affair for the browser to reify the encoded AST into a compatible representation, especially if comments are also eventually preserved (per article its on the roadmap)
- Yoric 9y agoIt would be interesting to find any library that actually depends on that. There used to be some, but I haven't seen any in years. If you do find one, please feel free to add a comment on the blog or one of the trackers :)
- mnarayan01 9y agoI remember reading about some framework which was doing something nutty like embedding actual data in the comments on a function, and then parsing out those comments at run-time. For what it's worth, I believe it was on HN and in relation to the caveats for older V8 optimization w.r.t. function length (https://top.fse.guru/nodejs-a-quick-optimization-advice-7353b820c92e https://top.fse.guru/nodejs-a-quick-optimization-advice-7353...), but it was years ago so, as you say, hopefully they moved to something less insane in the intervening time. Aside since you're here. The "Would it be possible to write a tool to convert serialized AST back to JS?" portion of the FAQ (https://github.com/syg/ecmascript-binary-ast#faq https://github.com/syg/ecmascript-binary-ast#faq) says that it would be possible to generate source which would be "semantically equivalent" -- you might want to call out the Function.prototype.toString exception explicitly there, though admittedly that level of pedantry might be more obscuring than enlightening.
- TazeTSchnitzel 9y agoIt's really exciting that this would mean smaller files that parse faster, but also more readable!
- megamindbrian 9y agoCan you work on webpack instead?
- Yoric 9y agoI personally hope that webpack can eventually support this format. But we're not there yet.
- nine_k 9y agoThis is what BASIC interpreters on 8-bit systems did from the very beginning. Some BASIC interpreters did not even allow you to type the keywords. Storing a trivially serialized binary form of the source code is a painfully obvious way to reduce RAM usage and improve execution speed. You can also trivially produce the human-readable source back. It's of course not compilation (though parsing is the first thing a compiler would do, too). It's not generation of machine code, or VM bytecode. it's mere compression. This is great news because you got to see the source if you want, likely nicely formatted. You can also get rid of the minifiers, and thus likely see reasonable variable names in the debugger.
- thanatropism 9y agoHa, great memories of the ZX Spectrum programming-keyword keyboard!
- d--b 9y agoI am puzzled by how an binary AST makes the code significantly smaller than a minified+gziped version. A JavaScript expression such as: var mystuff = blah + 45 Gets minified as var a=b+45 And then what is costly in there is the "var " and character overhead which you'd hope would be much reduced by compression. The AST would replace the keywords by binary tokens, but then would still contain function names and so on. I mean I appreciate the effort that shipping an AST will cut an awful lot of parsing, but I don't understand why it would make such a difference in size. Can someone comment?
- bryanlarsen 9y agoAccording to a comment by Yoric, they're seeing a 5% improvement in size over minified+gzip. https://news.ycombinator.com/item?id=15046750 https://news.ycombinator.com/item?id=15046750
- AriaMinaei 9y agoAfaik, improving parse time is the big goal here. Parsing is a significant stage of the compile pipeline, perf-wise. Some engines (Chakara at least), defer part of the parsing of the body of a function until the function itself is called, just to save precious milliseconds and not block the first render.
- kannanvijayan 9y agoIt's actually hard to get smaller than compressed minified JS. Source code is actually a very excellent high-level, compact representation of program text. The space optimizations in BinaryJS are to get us back down to the point where we are as good or better than minified compressed JS. The main goal is to allow for much faster parse times, but to do that without compromising other things like compressed source size.
- Existenceblinks 9y agoThese are random thought I just wrote on twitter in the morning(UTC+7): "I kinda think that there were no front-end languages actually. It's kinda all about web platform & browsers can't do things out of the box." "Graphic interface shouldn't execute program on its own rather than rendering string on _platform_ which won't bother more." "This is partly why people delegate js rendering to server. At the end of the day all script should be just WebAssembly bytecodes sent down." "Browser should act as physical rendering object like pure monitor screen. User shouldn't have to inspect photon or write photon generators." "SPA or PWA is just that about network request reduction, and how much string wanted to send at a time & today http/2 can help that a lot." "Project like Drab https://github.com/grych/drab https://github.com/grych/drab 's been doing quite well to move computation back to "server" (opposite to self-service client)" "WebAssembly compromise (to complement js) to implement the platform. JS api and WebAssembly should be merged or united." "VirtualDom as if it is a right way should be built-in just like DOM get constructed from html _string_ from server. All JS works must die." "That's how WebComponent went almost a half way of fulfilling web platform. It is unfortunate js has gone far, tools are actively building on" "I'd end this now before some thought of individualism-ruining-the-platform take over. That's not gonna be something i'd like to write (now)" ----- Not a complete version though. Kind of general speaking but I've been thinking in detail a bit. Then hours later I found this thread.
- kyle-rb 9y agoThe linked article somehow avoids ever stating the meaning of the acronym, and I had to Google it myself, so I imagine some other people might not know: AST stands for "abstract syntax tree". https://en.wikipedia.org/wiki/Abstract_syntax_tree https://en.wikipedia.org/wiki/Abstract_syntax_tree
- Yoric 9y agoGood point, I'll add this to the article.
- tolmasky 9y agoOne of my main concerns with this proposal, is the increasing complexity of what was once a very accessible web platform. You have this ever increasing tooling knowledge you need to develop, and with something like this it would certainly increase as "fast JS" would require you to know what a compiler is. Sure, a good counterpoint is that it may be incremental knowledge you can pick up, but I still think a no-work make everything faster solution would be better. I believe there exists such a no-work alternative to the first-run problem, which I attempted to explain on Twitter, but its not really the greatest platform to do so, so I'll attempt to do so again here. Basically, given a script tag: <script src = "abc.com/script.js" integrity="sha256-123"></script> A browser, such as Chrome, would kick off two requests, one to abc.com/script.js, and another to cdn.chrome.com/sha256-123/abc.com/script.js. The second request is for a pre-compiled and cached version of the script (the binary ast). If it doesn't exist yet, the cdn itself will download it, compile it, and cache it. For everyone except the first person to ever load this script, the second request returns before the time it takes for the first to finish + parse. Basically, the FIRST person to ever see this script online, takes the hit for everyone, since it alerts the "compile server" of its existence, afterwards its cached forever and fast for every other visitor on the web (that uses chrome). (I have later expanded on this to have interesting security additions as well -- there's a way this can be done such that the browser does the first compile and saves an encrypted version on the chrome cdn, such that google never sees the initial script and only people with access to the initial script can decrypt it). To clarify, this solution addresses the exact same concerns as the binary AST issue. The pros to this approach in my opinion are: 1. No extra work on the side of the developer. All the benefits described in the above article are just free without any new tooling. 2. It might actually be FASTER than the above example, since cdn.chrome.com may be way faster than wherever the user is hosting their binary AST. 3. The cdn can initially use the same sort of binary AST as the "compile result", but this gives the browser flexibility to do a full compile to JIT code instead, allowing different browsers to test different levels of compiles to cache globally. 4. This would be an excellent way to generate lots of data before deciding to create another public facing technology people have to learn - real world results have proven to be hard to predict in JS performance. 5. Much less complex to do things like dynamically assembling scripts (like for dynamic loading of SPA pages) - since the user doesn't also have to put a binary ast compiler in their pipeline: you get binary-ification for free. The main con is that it makes browser development even harder to break into, since if this is done right it would be a large competitive advantage and requires a browser vendor to now host a cdn essentially. I don't think this is that big a deal given how hard it already is to get a new browser out there, and the advantages from getting browsers to compete on compile targets makes up for it in my opinion.
- mannschott 9y agoThis is reminiscent of the technique used by some versions of ETH Oberon to generate native code on module loading from a compressed encoding of the parse tree. Michael Franz described the technique as "Semantic-Dictionary Encoding": «SDE is a dense representation. It encodes syntactically correct source program by a succession of indices into a semantic dictionary, which in turn contains the information necessary for generating native code. The dictionary itself is not part of the SDE representation, but is constructed dynamically during the translation of a source program to SDE form, and reconstructed before (or during) the decoding process. This method bears some resemblance to commonly used data compression schemes.» See also "Code-Generation On-the-Fly: A Key to Portable Software" https://pdfs.semanticscholar.org/6acf/85e7e8eab7c9089ca1ff24531c341168f93c.pdf https://pdfs.semanticscholar.org/6acf/85e7e8eab7c9089ca1ff24... This same technique also was used by JUICE, a short-lived browser plugin for running software written in Oberon in a browser. It was presented as an alternative to Java byte code that was both more compact and easier to generate reasonable native code for. https://github.com/Spirit-of-Oberon/Juice/blob/master/JUICE.txt https://github.com/Spirit-of-Oberon/Juice/blob/master/JUICE.... I seem to recall that the particular implementation was quite tied to the intermediate representation of the OP2 family of Oberon compilers making backward compatibility in the face of changes to the compiler challenging and I recall a conversation with someone hacking on Oberon that indicated that he'd chosen to address (trans)portable code by the simple expedient of just compressing the source and shipping that across the wire as the Oberon compiler was very fast even when just compiling from source. I'm guessing the hard parts are: (0) Support in enough browsers to make it worth using this format. (1) Coming up with a binary format that's actually significantly faster to parse than plain text. (SDE managed this.) (2) Designing the format to not be brittle in the face of change.
- Yoric 9y agoVery interesting, thanks. Indeed, one of the challenges was designing a format that will nicely support changes to the language. I believe that we have mostly succeeded there, and I'll blog about it once I find a little time. Now, of course, the next challenge is making sure that the file is still small enough even though we are using this future-proof format. We haven't measured this yet, but I expect that this will need additional work.
- iamleppert 9y agoI'd like to see some real-world performance numbers when compared with gzip. The article is a little overzealous in its claims that simply don't add up. My suspicion is it's going to be marginal and not worth the added complexity for what essential is a compression technique. This project is a prime example of incorrect optimization. Developers should be focused on loading the correct amount of JavaScript that's needed by their application, not on trying to optimize their fat JavaScript bundles. It's so lazy engineering.
- apaprocki 9y agoIt's specifically not trying to reduce size. It's trying to reduce time spent parsing in the JS engine.
- Yoric 9y agoI'm guilty here: I described this format as "compression technique" because early feedback indicated that many people assumed this was a new bytecode. However, the main objective is indeed to speed up parsing. Compressing the file is a secondary goal. > My suspicion is it's going to be marginal and not worth the added complexity for what essential is a compression technique. In terms of raw file size and according to early benchmarks (which may, of course, be proved wrong as we progress), Binary AST + gzip affords us a compression that is a little bit better than minification + gzip. By opposition to minification, Binary AST does not obfuscate the code. The real gain is in terms of parsing speed, in which we get considerable speedups. I do not want to advertise detailed numbers yet because people might believe them, and we are so early in the development process that they are bound to change dozens of time. > This project is a prime example of incorrect optimization. Developers should be focused on loading the correct amount of JavaScript that's needed by their application, not on trying to optimize their fat JavaScript bundles. It's so lazy engineering. Well, you are comparing optimizing the language vs. optimizing the code written in that language. These two approaches are and always will be complementary.
- syg 9y agoThe gzip point aside (which is not an apples-to-apples comparison as gzipping a big source does not diminish its parse time), I see the response of "JS devs need to stop shipping so much JS" often. My issue with this response is that multiple parties are all trying to work towards making JS apps load faster and run faster. It is easy enough to say "developers should do better", but that can be an umbrella response to any source of performance issues. The browser and platform vendors do not have the luxury of fiat: they cannot will away the size of modern JS apps simply because they are causing slowdown. There can be engineering advocacy, to be sure, but that certainly shouldn't preclude those vendors from attempting technical solutions.
- s3th 9y agoi'm very skeptical about the benefits of a binary JavaScript AST. The claim is that a binary AST would save on JS parsing costs. however, JS parse time is not just tokenization. For many large apps, the bottleneck in parsing is instead in actually validating that the JS code is well-formed and does not contain early errors. The binary AST format proposes to skip this step [0] which is equivalent to wrapping function bodies with eval… This would be a major semantic change to the language that should be decoupled from anything related to a binary format. So IMO proposal conflates tokenization with changing early error semantics. I’m skeptical the former has any benefits and the later should be considered on its own terms. Also, there’s immense value in text formats over binary formats in general, especially for open, extendable web standards. Text formats are more easily extendable as the language evolves because they typically have some amount of redundancy built in. The W3C outlines the value here (https://www.w3.org/People/Bos/DesignGuide/implementability.html https://www.w3.org/People/Bos/DesignGuide/implementability.h...). JS text format in general also means engines/interpreters/browsers are simpler to implement and therefore that JS code has better longevity. Finally, although WebAssembly is a different beast and a different language, it provides an escape hatch for large apps (e.g. Facebook) to go to extreme lengths in the name of speed. We don’t need complicate JavaScript with such a powerful mechanism already tuned to perfectly complement it. [0]: https://github.com/syg/ecmascript-binary-ast/#-2-early-error-semantics https://github.com/syg/ecmascript-binary-ast/#-2-early-error...
- syg 9y agoEarly error behavior is proposed to be deferred (i.e. made lazy), not skipped. Additionally, it is one of many things that require frontends to look at every character of the source. I contend that the text format for JS is no way easy to implement or extend, though I can only offer my personal experience as an engine hacker.
- s3th 9y agoIf early error is deferred then it's no longer early... that's all I meant by skipped. It still is a semantic change that's unrelated to a binary AST.
- deleted 9y ago[deleted]
- svat 9y agoHowever this technology pans out, thank for a really well-written post. It is a model of clarity. (And yet many people seem to have misunderstood: perhaps an example or a caricature of the binary representation might have helped make it concrete, though then there is the danger that people will start commenting about the quality of the example.)
- c-smile 9y agoTo be honest I (as an author of the Sciter [1]) do not expect too much gain from that. Sciter contains source code to bytecode compiler. Those bytecodes can be stored to files and loaded bypassing compilation phase. There is not too much gain as JS alike grammar is pretty simple. In principle original ECMA-262 grammar was so simple that you can parse it without need of AST - direct parser with one symbol lookahead that produces bytecodes is quite adequate. JavaScript use cases require fast compilation anyway. As for source files as for eval() and alike cases like onclick="..." in markup. [1] https://sciter.com https://sciter.com And JS parsers used to be damn fast indeed, until introduction of arrow functions. Their syntax is what requires AST.
- timdorr 9y agoHow do you do one-symbol-lookahead with things like function hoisting? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Function_declaration_hoisting https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- c-smile 9y agoNot clear how hoisting is related to parsing really ... Compiler builds table of variables (registers map) of the function to generate proper bytecodes to access registers. At this point hoisting has some effect. But it has nothing with parse/AST phase.
- limeblack 9y agoI have never been a fan of the => syntax. Although that really isn't the point. What about the syntax slows parsing?
- c-smile 9y agoAs I said original JS syntax is pretty simple - parsing is comparable with just scanning source buffer char by char. Not too much different from HTML and CSS. Where 99% of time takes actual DOM creation. Like this XML/HTML scanner that I did while ago: https://www.codeproject.com/Articles/14076/Fast-and-Compact-HTML-XML-Scanner-Tokenizer https://www.codeproject.com/Articles/14076/Fast-and-Compact-... - it as fast as access to memory of HTML source. It even does not allocate any memory while parsing.
- iainmerrick 9y agoThis article says "Wouldn’t it be nice if we could just make the parser faster? Unfortunately, while JS parsers have improved considerably, we are long past the point of diminishing returns." I'm gobsmacked that parsing is such a major part of the JS startup time, compared to compiling and optimizing the code. Parsing isn't slow! Or at least it shouldn't be. How many MBs of Javascript is Facebook shipping? Does anyone have a link to some measurements? Time spent parsing versus compilation?
- sltkr 9y agoI think the main issue with parsing is that you probably need to parse all JavaScript before you can start executing any of it. That might lead to a high delay before you can start running scripts. Compiling and optimizing code can be slow, too, but JIT compilers don't optimize all code that's on a page. At least at first, the code gets interpreted, and only hot code paths are JIT compiled, probably in a background threads. That means that compiling/optimizing doesn't really add to the page load latency. But I agree with you that this is a strange suggestion. If parsing is so slow, maybe browsers should be caching the parsed representation of javascript sources to speed up page loading, or even better: the bytecode/JIT-generated code.
- sjrd 9y ago> If parsing is so slow, maybe browsers should be caching the parsed representation of javascript sources to speed up page loading, or even better: the bytecode/JIT-generated code. This is addressed in the article: https://yoric.github.io/post/binary-ast-newsletter-1/#improving-caching https://yoric.github.io/post/binary-ast-newsletter-1/#improv...
- hashseed 9y agoChrome already caches compile result for previously visited pages to bypass the initial parsing/compiling.
- Yoric 9y agoSo does Firefox, btw. This is addressed here: https://yoric.github.io/post/binary-ast-newsletter-1/#improving-caching https://yoric.github.io/post/binary-ast-newsletter-1/#improv...
- z3t4 9y agoI wish for something like evalUrl() to run code that has already been parsed "in the background" so a module loader can be implemented in userland. It would be great if scripts that are prefetched or http2 pushed could be parsed in parallel and not have to be reparsed when running eval.
- limeblack 9y agoCould the AST be made an extension of the language similar to how it works in Mathematica?
- Yoric 9y agoWhat do you mean? How does it work in Mathematica?
- chr1 9y agoMathematica has several representations for the code the main one is the inputForm, the thing that users type in, and there is a fullForm which is the full ast, and there is a way to manipulate it to create new functions on the fly (or really any other objects, like graphic or sound, since everything in Mathematica is represented in a uniform way) For instance if in input form you have {1 + 1, 2 *3 }, in fullForm this becomes List[Plus[1,1], Times[2, 3]], which is the readable version of lisp and internally represented the same way [List [Plus 1 1] [Times 2 3]]. The fullForm is accessible from the language, and can be manipulated using standard language feature, kind of like eval but better. It would be really cool to have something like this in javascript, but unfortunately looks like javascript tools tend to create nonuniform ast, that is hard to traverse and manipulate
- Yoric 9y agoFor the moment, we're not trying to make the AST visible to the language although this would definitely be interesting. The "recommended" manner to manipulate the AST these days is to use e.g. Babel/Babylon or Esprima. I realize that it's not as integrated as what you have in mind, of course, but who knows, maybe a further proposal one of these days?
- mnemotronic 9y agoYea! A whole new attack surface. A hacked AST file could cause memory corruption and other faults in the browser-side binary expander.
- Yoric 9y agoSure, a new file format always introduces a new risk. This has never prevented browsers from adding support for new image formats or compression schemes, though.