Live data from Hacker News

Deep Dive into PHP 8's JIT

thephp.website

51–60 of 66 posts

Re: Deep Dive into PHP 8's JIT

#51
post #50

This article is actually now quite out of date as PHP has switched to a tracing JIT which appears to be heavily based on LuaJIT. https://github.com/php/php-src/pull/5874 https://github.com/php/php-src/commit/4bf2d09edeb14467ba7955...

Any ideas why they’ve moved from a method-based JIT to tracing? AFAIK tracing JITs are generally inferior to method-based ones, which is why none of the major JavaScript engines use tracing. Their only advantage seems to be (relative) simplicity, which is essential for the lightweight LuaJIT but not for PHP.

That doesn't sound right. How would a trace-based JIT be easier to implement? There was a research project which made HotSpot into a trace-based JIT. It reported both faster compilation times, and superior quality of generated code.

(I don't know if the HotSpot folks ever considered adopting the changes.)

http://www.ssw.jku.at/Research/Papers/Haeubl11/

Re: Deep Dive into PHP 8's JIT

#52
post #2

Tiny nitpick: the article describes JavaScript as an interpreted language without JIT when most major JS engines do have JIT optimisation. It’s difficult to make this call about any language with more than one implementation. But anyway, kudos to the PHP folks for yet another improvement. It’s been a long time since I used it but I’m continually impressed by how far it’s come. And it’s a useful test to how flexible a…

I should probably add this kind of thing to the article then. It is nearly impossible to state "Language X is compiled/interpreted/jitted".

I didn't explicitly say that JS doesn't come with JIT, because I'd be putting Node.JS and every browser engine in the same bag. I simply can't be sure about all of them.

I'll add very soon this caveat that the dialect (js, php, python) doesn't really matter and make it clear that I'm talking about engines, possibly directly point to them.

I hope you understand, though, that I wanted to make JIT as a concept understandable. The language comparisons are secondary.

Thanks a lot for your feedback!

Re: Deep Dive into PHP 8's JIT

#53
post #36

Unless we are speaking about Java before Java 1.2, it is definitely not interpreted, there are plenty of JIT and AOT implementations without any kind of interpretation step. Since 25 years, time to learn that implementations and languages are not the same.

I might be wrong here, as I'm not so close to Java development. But a language implementing JIT, at least to me, is interpreted.

Could you please point an implementation detail where a JIT-capable engine doesn't include interpretation in its runtime?

In every case, thanks a lot for your feedback!

Re: Deep Dive into PHP 8's JIT

#54

There is a small error in the text. When describing the opcache.jit setting it shows examples where the third flag is set to 5, eg 1255, but the table of possible values for the third flag, 'T - JIT trigger', goes from 0 to 4.

Thanks a lot! I blindly fetched this from the reference mentioned there. I'll update this as soon as I have time (probably during this week) and also let the author of the referenced post know about it.

Re: Deep Dive into PHP 8's JIT

#55
post #50

This article is actually now quite out of date as PHP has switched to a tracing JIT which appears to be heavily based on LuaJIT. https://github.com/php/php-src/pull/5874 https://github.com/php/php-src/commit/4bf2d09edeb14467ba7955...

Any ideas why they’ve moved from a method-based JIT to tracing? AFAIK tracing JITs are generally inferior to method-based ones, which is why none of the major JavaScript engines use tracing. Their only advantage seems to be (relative) simplicity, which is essential for the lightweight LuaJIT but not for PHP.

The method JIT they built before failed to provide any improvements on a real world app. Building a JIT compiler for a dynamic language that's actually faster than a fast interpreter is quite tricky!

There's a lot more to it than just compiling what the interpreter does. CRuby's JIT has a different approach using C templating rather than Dynasm and templating/context threading but it also fails to improve performance much for the same reasons.

Tracing JITs are really good at optimizing a small scope. What a tracing JIT does with recording a single path of linear control flow the method JITs also try to do with branch profiling and pruning.

It works really well for a particular style of Lua. For a language like Ruby or PHP it's a lot harder to make a tracing JIT work well on existing code.

The main problem is tail duplication causes the number of traces to increase exponentially with each branch. You have to either have trace heuristics which keep the traces very short or go half way to a method JIT and build a control flow graph.

I got to the tail explosion problem building a tracing JIT for CRuby and gave up.

Re: Deep Dive into PHP 8's JIT

#56
post #50

Earlier quoted context omitted.

Any ideas why they’ve moved from a method-based JIT to tracing? AFAIK tracing JITs are generally inferior to method-based ones, which is why none of the major JavaScript engines use tracing. Their only advantage seems to be (relative) simplicity, which is essential for the lightweight LuaJIT but not for PHP.

That doesn't sound right. How would a trace-based JIT be easier to implement? There was a research project which made HotSpot into a trace-based JIT. It reported both faster compilation times, and superior quality of generated code. (I don't know if the HotSpot folks ever considered adopting the changes.) http://www.ssw.jku.at/Research/Papers/Haeubl11/

> How would a trace-based JIT be easier to implement?

When compiling at method-granularity, with incomplete information about types, complex features are required e.g. On-Stack Replacement (if the current method becomes "hot", it needs to be replaced by a compiled version), Inline Caches, Hidden Classes and Deoptimization.

In a trace-based JIT, all these features can be replaced by "just compile another trace".

Re: Deep Dive into PHP 8's JIT

#57
post #56

Earlier quoted context omitted.

That doesn't sound right. How would a trace-based JIT be easier to implement? There was a research project which made HotSpot into a trace-based JIT. It reported both faster compilation times, and superior quality of generated code. (I don't know if the HotSpot folks ever considered adopting the changes.) http://www.ssw.jku.at/Research/Papers/Haeubl11/

> How would a trace-based JIT be easier to implement? When compiling at method-granularity, with incomplete information about types, complex features are required e.g. On-Stack Replacement (if the current method becomes "hot", it needs to be replaced by a compiled version), Inline Caches, Hidden Classes and Deoptimization. In a trace-based JIT, all these features can be replaced by "just compile another trace".

We need all those complex features with tracing JITs too. Getting into a trace is basically OSR. Exiting a trace and restoring the interpreter state is basically an OSR exit or deoptimization. It's really just different terminology for the same thing. Inline caches on method calls become guards. We can't just ignore them.

LuaJIT does without hidden classes or property caching because on-trace it's able to eliminate table access and allocation. Performance tanks on OO Lua once you fall off trace. You can work around it with "compile another trace" in a sense that works as long as you have infinite cache.

Re: Deep Dive into PHP 8's JIT

#58
post #36

Unless we are speaking about Java before Java 1.2, it is definitely not interpreted, there are plenty of JIT and AOT implementations without any kind of interpretation step. Since 25 years, time to learn that implementations and languages are not the same.

I might be wrong here, as I'm not so close to Java development. But a language implementing JIT, at least to me, is interpreted. Could you please point an implementation detail where a JIT-capable engine doesn't include interpretation in its runtime? In every case, thanks a lot for your feedback!

V8 had only baseline compilation until much later https://v8.dev/blog/ignition-interpreter

It's not super exotic to do this.

Re: Deep Dive into PHP 8's JIT

#59

"PHP as fast as C" - People who are in php language development may die laughing reading this statement. Truth can be harsh, but people sometime overvalue to such an extent is hard to understand.

Well, most of php is just calling C functions. So if they add a JIT to that, it could be a believable claim. Why not?

No implementation of a language as dynamic as something like PHP has ever managed it in practice. TruffleRuby uses Java for particularly performance sensitive parts. JSC relies on calling C++ or "intrinsics" which are hand-written IR snippets of code to JIT.

Re: Deep Dive into PHP 8's JIT

#60
post #43
post #29

Earlier quoted context omitted.

C is frequently 100x faster than Python for code like the example I showed. With autovectorization and other optimizations it can be 500x. So if a Python JIT does 10-50x better than CPython on a numeric workload, that sounds impressive, but it's still slow compared to C. And again they don't get 10-50x on string/hash/method call workloads. I think they're lucky to get 2x in some of those cases.

Actually a lot of string stuff is just calling into C, and can be as fast a C (and often is).

Just calling into C doesn't give the performance you’re after a lot of the time. The compiler needs to be aware of the properties of strings. Usually they're implemented as either dedicated opcodes or intrinsics. You can see the simple ones in LuaJIT here https://github.com/LuaJIT/LuaJIT/blob/ff1e72acead01df7d8ed0f...
Post reply on HN