Hacker News new | ask | show | jobs
by sabauma 2839 days ago
This is indeed a consequence of tracing. The problem is that traces are associated to loops in the program, and since the map function contains only one loop, all traces for map are associated to the loop in its implementation.

When you manually write a loop, there is only one 'body', so a tracing JIT turns that into a single or small number of traces.

For the loop inside of map, you need to produce side exits and new traces for each function passed in. The more times map is used, the slower it gets. This is made worse by the fact that traces out of side exits tend to not be optimized nearly as well.

Pycket has this same issue with its builtin (or hand written) looping _functions_ like map. Fortunately, Racket provides many useful looping macros which allows Pycket to generate unique traces for each loop, ameliorating this problem somewhat in Pycket.

1 comments

For the loop inside of map, you need to produce side exits and new traces for each function passed in.

Is it true to say that if two functions have the same body and arglist, and capture no variables, then you should be able to reuse the same traces?

This doesn’t happen very often in real code, but it’s useful to understand the problem.

In theory if you call map again with an identical function it should still fall inside the original trace. Tracing JITs effectively inline all function calls that happen inside the trace so if two functions contain the same body they would be indistinguishable.

But there are all sorts of reasons why this might not be happening in that bug report I linked to. It might be due to the definition of the map and reduce functions (luafun adds lots of features to them, so its not just a simple straightforward loop) or it could be due to something about luajit (it is a complex piece of software after all).

The only way to know for sure would be to examine the traces with "luajit -jdump"

I think in the case of a JITed function in a dynamic language, whether the body is the "same" or not depends on how the interface used by the function is monomorphized - which in turn depends on the trace.