5 ms·
Too much wishful thinking during the second half of the talk, though. Also, while fancy runtime systems can improve the performance of dynamic[0] languages, it
by catnaroek 10y ago
Too much wishful thinking during the second half of the talk, though.
Also, while fancy runtime systems can improve the performance of dynamic[0] languages, it doesn't come for free: the price to be paid is the loss of elegance. For instance, a JIT compiler could inline a virtual method that seems not to be overridden anywhere, but if later on it turns out that the virtual method was overridden somewhere, the “optimization” has to be undone. How can anyone in their right mind trust a language that requires such dirty implementation tricks to achieve decent performance?
[0] By which I mean “less amenable to static analysis”, regardless of whether the language has a static type system. For instance, Java and C# are dynamic languages in this sense.
- smallnamespace 10y ago> How can anyone in their right mind trust a language that requires such dirty implementation tricks to achieve decent performance? Isn't this a rather broad brush with which to paint all JIT language implementations, including Java, C#, and, say, PyPy?
- catnaroek 10y agoCould you name a JIT compiler that doesn't do this kind of thing, yet offers performance comparable to AOT-compiled languages? (FWIW, I'm not saying it's impossible. It's perfectly possible, but you'd need a source language that offers much better static guarantees than the typical language that a JIT compiler is written for.) --- Sorry, can't reply to you directly, because “I'm submitting too fast”. So my reply goes here: > for the simple reason that type systems cannot capture all relevant runtime context. Type checking isn't the only kind of static analysis out there. And there's no need to use statistics to optimize anything at runtime when your ahead-of-time compilation step already emits optimal target machine code. > Java is a good example here, since it's strongly statically typed. Java is as dynamically typed as it gets: `instanceof`, downcasts and reflection, all conspire to reduce the usefulness of static type information to zero. > By your reckoning, all greedy optimizations that CPUs do like branch prediction and prefetching are also similarly 'inelegant', because they can be wrong and require rolling back. Yes, indeed. It's more elegant to know beforehand what exactly you have to do, and then do just that and nothing else.
- smallnamespace 10y ago> that _doesn't_ do this kind of thing Why does that matter to anyone? > you'd need a source language that offers much better static guarantees than the typical language that a JIT compiler is written for Java and C# are both statically, strongly typed languages where JITs are the dominant implementation. Almost by definition, it's impossible to write a JIT compiler that outperforms AOT compilation without looking at runtime data, because AOT compilers have a lot more time to look for difficult static optimizations. The reason JITs can keep up is because they have access to information that an AOT compiler does not. > And there's no need to use statistics to optimize anything at runtime when your ahead-of-time compilation step already emits optimal target machine code. This is simply untrue. For example, it's not possible to statically determine whether a function should be inlined or not. However, a JIT can see that it's used in a hot loop and dynamically inline. For any language, no matter the type system, runtime information will always be a superset of compile-time information. There will always exist optimizations in a JIT that aren't possible in an AOT compiler. > Java is as dynamically typed as it gets: `instanceof`, downcasts and reflection, all conspire to reduce the usefulness of static type information to zero. Idiomatic Java code doesn't use these features heavily. Just because it's possible to wipe out type information doesn't mean that the vast majority of code that an AOT or JIT compiler sees won't be strongly typed.
- catnaroek 10y ago> For example, it's not possible to statically determine whether a function should be inlined or not. MLton has absolutely no problems inlining functions, even higher-order functions, at compile time. This is only difficult in languages with virtual methods, because they can be overridden anywhere. If anything, that's an indictment of virtual methods, not AOT compilers. > However, a JIT can see that it's used in a hot loop and dynamically inline. What if it's a virtual method call that's known to be overridden in several places? You can't inline it, even if it's in the middle of a hot loop. > For any language, no matter the type system, runtime information will always be a superset of compile-time information. Runtime information is always anecdotal, specific to one particular run of a program, so... > There will always exist optimizations in a JIT that aren't possible in an AOT compiler. ... for every “optimization” a JIT can perform, there will always exist a program for which the “optimization” will have to be rolled back after it has already been performed, because it turned out to be unsound. > Idiomatic Java code doesn't use these features heavily. Language implementations must work correctly whether you write idiomatic or unidiomatic code. > Just because it's possible to wipe out type information doesn't mean that the vast majority of code that an AOT or JIT compiler sees won't be strongly typed. Most code I write in Python could be given static types too. That doesn't make Python a statically typed language. And “strongly typed” doesn't really mean anything.
- contextfree 10y agoit's interesting that C# has recently moved away from JIT and reflection for client apps (.NET Native), though.
- mafribe 10y agotrust a language that ... Where's the problem? JIT compilers work. Most high-level languages require compiler tricks for achieving performance from Scala to Haskell to Prolog. It's useful to distinguish between (1) having a clean, easy to understand semantics and (2) having a fast implementation. Use all the hackery in the world to get your language fast, as long as it's abstract semantics is easy and canonical.
- catnaroek 10y ago> Most high-level languages require compiler tricks for achieving performance from Scala to Haskell to Prolog. To make things perfectly clear: I'm not against optimizations being performed automatically by compilers or runtime systems. What I'm against is unclean designs: deliberately performing an unsound optimization and then rolling it back is an unclean design. > Use all the hackery in the world to get your language fast, The language implementation is a program itself, and I don't have any good reasons to trust a hackish language implementation any more than I trust other hackish programs - that is, not at all. > as long as it's abstract semantics is easy and canonical. Hah! This thread is about JavaScript.
- mafribe 10y agois an unclean design. It's not unsound. Otherwise you'det g incorrect results. You could say the design is wasteful, because you optimise and then throw away the optimisation. But it's hard to do better for some kinds of languages. trust a hackish language implementation I agree. And indeed JIT compilers are hard to get right. But in practise even JIT compilers are much higher quality than applications: ask yourself, how many of the bugs in your code turned out to be compiler bugs, vs how many were ultimately your mistakes?
- catnaroek 10y ago> It's not unsound. Otherwise you'd incorrect results. You could say it's wasteful, because you optimise and then throw away the optimisation. The optimization is unsound. If it weren't, it wouldn't have to be rolled back occasionally. If you're talking about the combination of the optimization and the rollback mechanism, it's not unsound, but it's inelegant. A runtime system designed this way only understands your program in a statistical sense (based on concrete execution profiles, which may vary from one run to another), never with the full certainty that static analyses (type checking, abstract interpretation) can give you. > how many of the bugs in your code turned out to be compiler bugs, vs how many were ultimately your mistakes? Of course, most were my mistakes. But the very reason why those bugs made it into the final executable is the lack of powerful static analyses in the first place. Curiously enough, when I use languages that make static analyses possible, I write programs with less bugs and they perform better without relying on fancy runtime system tricks. --- Sorry, can't reply to you guys, because “I'm submitting too fast”. So my replies go here: @mafribe: > That's an orthogonal issue. It's not. Static analyses gather valuable information that can be used to emit efficient code. > More powerful static analysis is also more time-consuming. So perform it ahead of time! > One of the design goals of Javascript JITs is to make web-pages as responsive as possible. That rules out complicated static analysis. Of course, a browser can't spend much time statically analyzing JavaScript programs, but programs can be statically analyzed (gasp!) before they're deployed. --- @smallnamespace: > Why does that matter to anyone? Because this implementation technique is unnecessarily complex, and a far simpler alternative exists: Know beforehand what your program has to do. Think before you write code. > Java and C# are both statically, strongly typed languages where JITs are the dominant implementation. Their type systems can be easily subverted, so they're not “strongly typed” in my book. --- @smallnamespace: Oops, sorry, I accidentally swapped my two replies to you: this one and https://news.ycombinator.com/item?id=12481956 https://news.ycombinator.com/item?id=12481956 .