5 ms·
I don't understand why people keep making js-to-native compilers. the result is always less performance that what modern js engines can do to the original sourc
by snek 8y ago
I don't understand why people keep making js-to-native compilers. the result is always less performance that what modern js engines can do to the original source code, because all those runtime behaviours the author mentions build up really fast. js engines actually run the code and figure out the types and such to create highly optimized machine code.
- nicoburns 8y agoYeah, the JS runtimes are really impressive. I'd be interested to see what a compiler could do with TypeScript though. There could perhaps be guidelines of which features you can use in hot code paths in order to get optimised code, which could be enforced by the compiler for sections of the code which you mark...
- chrisseaton 8y agoI would imagine JS JITs can determine more specific types at runtime than you can express in TypeScript source code.
- jdc 8y agoCould you ELI5 why you think that?
- chrisseaton 8y agoTypeScript lets you annotate that a parameter will only ever be a number, but the JIT can find that out for itself by seeing that it’s only ever a number when it runs the program and a number is all you pass to it, using stamps and class profiling. The JIT can also see types beyond that, like that it’s only ever a number and it’s always below 0xff, using stamps and value profiling. The JIT has to guard that the type is as expected, yes, but so would the static compiler in order to do the more specific types.
- z3t4 8y agoLets say you've built a house in lego. But the computer do not know it's actually a house. Something called a compiler has to take apart the lego house, then package the parts in groups of 8,16,32 or 64 (dissembles the house into stacks with 8 lego bit's in each). Then the compILer have to tell the compUter what to do with the stacks, and what each stack is. For example take this stack with red pieces and this stack with green pieces and build a wall, then take these bits, and combine with these bits to build a roof, etc. The computer is dumb, but it's very fast.
- masklinn 8y ago> Yeah, the JS runtimes are really impressive. I'd be interested to see what a compiler could do with TypeScript though. You can probably just compare AOT and JIT Java or C# implementations and get something of an upper bound. Actual improvements will likely depend on your use case: for short-running programs the overhead of the parsing, JIT machinery & interpretation might dwarf the execution time so even a straightforward compilation full of virtual calls will edge out the pre-JIT interpreter, however for longer-running programs the JIT should be able to devirtualise, inline and optimise the code much better than the AOT compiler will. Inlining is the most important optimisation, and it's hard to AOT inline dynamic dispatch.
- tjelen 8y agoI think that the AssemblyScript project is halfway there. It compiles a stricter subset of Typescript to webassembly format, which can be then translated to CPU-specific machine code.
- ridiculous_fish 8y agoModern JS engines rely on tracing JITs to achieve good performance. These optimizations only kick in once code has executed multiple times. But a lot of JS code executes only once, such as layout code running at app launch. Heck, lots of JS code executes zero times. This code still imposes a cost (parsing, etc). Consider the complaints about app launch time of Electron apps. A static compiler can be more effective at the runs-once or runs-zero cases.
- maxxxxx 8y agoCan the compiler really do much considering how dynamic Javascript is?
- ridiculous_fish 8y agoDepends on your definition of "much", but more than you might expect. Pre-parsing is an obvious big win, but there's also classical compiler optimizations: constant propagation, DCE, certain inlining, etc. Local variables can be statically determined to be non-captured, which means they can be stack allocated. One totally bizarre but profoundly useful property of JS is the restrictions on eval. eval has the ability to run new code, but this code is globally scoped unless it's run as the "eval" function itself. [1] Thus it's easy to decide which local variables are immune to eval; this in turn unlocks lots of optimizations. To my knowledge this weirdo behavior is not present in Python or other dynamic languages. 1: https://es5.github.io/#x15.1.2.1.1 https://es5.github.io/#x15.1.2.1.1
- timruffles 8y agoOh sure, it's just for fun/learning! Check my first post.
- pizlonator 8y agoOn the one hand, you’re totally right. But maybe there will be some breakthrough, so it’s important to stay open-minded. That breakthrough may be something modest like if this style of JS execution was better for some niche use case.
- roryrjb 8y agoIt may be slower, but I'd give up speed if this would result in less memory usage.
- jacobush 8y agoI could imagine a use case: you want to include some Javascript code base into your own EXE, but you don't want to drag in node.js or something heavy like that.
- a13n 8y agoMaybe you want to port some existing JS to another platform (eg. OS X, iOS, Android) where you want to run it natively rather than spinning up a JS engine and dealing with the bridge.