Earlier quoted context omitted.
The runtime watches the code run, and if it notices that a specific type is in use in a certain code section, it rewrites the generated code to use that type when possible. For example, if you want to add all the integers from 1 to 2^31, the JIT will eventually realize that the accumulator can be a register (with a machine int in it) instead of a JavaScript big integer. (If that overflows, it will switch back.) Obvio…
Often, there's more information at runtime than compile time. This may even be true at times for statically typed languages. I think the static/dynamic type debate is just a vestige of the state of interpreter/compiler technology in the 80's. I wish everyone would get over it and introspect and debug their knee-jerk reactions so we can get on with the next stage of language implementation.
Have Tracing JIT Compilers Won?
21–30 of 41 posts
Re: Have Tracing JIT Compilers Won?
#22With modern IDEs, tracing JIT, and type inference, I'm surprised that someone hasn't made the same lateral thinking sidestep that Hennessey & Patterson made for RISC. They offloaded much of the decoding work from the chip to the compiler, yielding faster chips in a smaller die size. Perhaps the Go language is the start of such a sidestep. We should be able to offload a lot of the work of type annotation to the IDE an…
You have just described Haskell. Annotate types if you want, let the compiler infer otherwise. Very dynamic feeling, but much safer. And you're right, it can make for some very fast code.
Re: Have Tracing JIT Compilers Won?
#23Earlier quoted context omitted.
That depends on whether you consider the Smalltalk and Self research at Sun and Xeroc PARC to be "academia". Much of the JVM optimization technology came directly from those. http://selflanguage.org/documentation/published/index.html The paper "An Efficient Implementation of Self" ( http://selflanguage.org/documentation/published/implementati... ) is a good overview. Lua is another language with a great JIT compiler,…
I was thinking Strongtalk + Tracing + Type inference.
Re: Have Tracing JIT Compilers Won?
#24Earlier quoted context omitted.
You have just described Haskell. Annotate types if you want, let the compiler infer otherwise. Very dynamic feeling, but much safer. And you're right, it can make for some very fast code.
I've always got the impression that Haskell's lazy properties makes it hard to reason about code performance. You can force high-performance code, but that requires circumventing the beauty of the language. Has this problem been solved?
OCaml isn't lazy-by-default, so reasoning about time/space performance is generally easier. It's worth considering as an alternative to Haskell.
Re: Have Tracing JIT Compilers Won?
#25Can somebody please explain what a tracing JIT is?
http://hacks.mozilla.org/2009/07/tracemonkey-overview/
http://ejohn.org/blog/tracemonkey/
http://weblogs.mozillazine.org/roadmap/archives/2008/08/trac...
These are tangentially related to the article topic, but gives you some sense of what tracing does.
Re: Have Tracing JIT Compilers Won?
#26Can somebody please explain what a tracing JIT is?
The runtime watches the code run, and if it notices that a specific type is in use in a certain code section, it rewrites the generated code to use that type when possible. For example, if you want to add all the integers from 1 to 2^31, the JIT will eventually realize that the accumulator can be a register (with a machine int in it) instead of a JavaScript big integer. (If that overflows, it will switch back.) Obvio…
Re: Have Tracing JIT Compilers Won?
#27Perhaps it's different in the Lua world, but it seems to me like this post is claiming the exact opposite of what the evidence suggests?
Don't get me wrong, here. I think trace trees are a very cool optimization technique and surely have a place in the future of JIT compilers. I just don't think they've “Won” at this point.
Re: Have Tracing JIT Compilers Won?
#28Earlier quoted context omitted.
Often, there's more information at runtime than compile time. This may even be true at times for statically typed languages. I think the static/dynamic type debate is just a vestige of the state of interpreter/compiler technology in the 80's. I wish everyone would get over it and introspect and debug their knee-jerk reactions so we can get on with the next stage of language implementation.
I think you're only considering static typing as an efficiency benefit. I'm equally as interested in its program-correctness benefits.
Edit: We appear to be in fierce agreement.
Re: Have Tracing JIT Compilers Won?
#29Earlier quoted context omitted.
I think you're only considering static typing as an efficiency benefit. I'm equally as interested in its program-correctness benefits.
Static typing and JIT compiling aren't mutually exclusive. You can do all the static analysis, checking, whole-program optimization, etc. that's feasible at compile time, compile to bytecode, and then do JIT compilation at runtime. Edit: We appear to be in fierce agreement.
Re: Have Tracing JIT Compilers Won?
#30Earlier quoted context omitted.
You have just described Haskell. Annotate types if you want, let the compiler infer otherwise. Very dynamic feeling, but much safer. And you're right, it can make for some very fast code.
I've always got the impression that Haskell's lazy properties makes it hard to reason about code performance. You can force high-performance code, but that requires circumventing the beauty of the language. Has this problem been solved?
Example; you have two threads in a producer/consumer setup. The first thread puts "g x" into the queue. The second thread removes this, and applies "f", and puts the result into a result queue. Then a result-processing thread prints those to the file.
You run this, and notice that it doesn't really take advantage of all cores. It seems to run slower on 2 or 3 cores than it does on 1 core, even though "f" and "g" are of roughly equal complexity and the application of each happens in a different thread! WTF?!?
The problem is, of course, that lazy evaluation "helped you". You never needed "g x" in the first thread, so it wasn't evaluated; the thunk was put in the queue. When you applied "f (g x)" in the second thread, you still didn't need the value of either computation, so it was never evaluated. You just put a thunk in the result queue. Finally, in the result-printing thread, you did need the result -- so all the work to evaluate the result was done there; in a single thread.
You realize this, switch to strict queues, and now your app is 2x faster.
(BTW, I simplified the producer/consumer model a bit. Normally you have one thread feeding work into a queue, n threads reading from that queue, doing work, and putting results into a result queue, and then a final result-aggregator thread. The end result would be the same; all the work would be done in that last thread. Slow!)