Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Add JIT optimization tool: lib.specialize(fn) #1053

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

lukego
Copy link
Member

@lukego lukego commented Oct 25, 2016

This branch contains a work-in-progress "design pattern" for making LuaJIT perform really aggressive optimizations under certain circumstances. This is based on the same technique that was recently used to optimize vhost-user (#1001).

The high-level intention is to make the pull() and push() methods of each app instance be JITed individually and to treat the app configuration parameters as if they were constants. JITing instances separately means that each one will have dedicated machine code and they will not interfere with each other (for example no collisions between instances like the ctype diversity in #612). Treating configuration parameters as constants is essentially "inlining" the configuration values as if they were written as constants in the source file i.e. allowing the optimizer to take advantage of their exact values. (The methods are re-JITed when the app configuration changes.)

The JIT is able to take this even further and to generate machine code that reference singleton objects (such as the app self object) using absolute addresses so it is not even necessary to assign a register to hold the address.

Likely some experience will be needed in order to use this feature effectively. Can also be that certain of these benefits are already available in practice without using this special feature.

Notably this will only be effective for apps that start JIT traces in their pull or push methods, which is loosely any app that includes a loop (for, while, or repeat) directly in its pull or push method. If we wanted this to also affect traces started in subroutines then we would need to take a slightly different approach. Could be that we can formulate this in a better way that is easier to understand. Caveat emptor.

This is intended as part of an overall effort to better understand the internal workings of LuaJIT in order to eventually explain them concisely and potentially also to identify tricks for generating code better than what is possible with an ahead-of-time static compiler.

See background discussion at LuaJIT/LuaJIT#208.

From the included documentation:

— Function **lib.specialize** *function*

Returns a clone of the given function with a shallow copy of its
function definition. The clone function has a separate bytecode
definition and any JIT traces that start in the clone will be
aggressively specialized by LuaJIT for the environment of the clone.

This can lead to especially efficient machine code when:
- The function being specialized contains a loop (`for` or `while` or `repeat`) directly in its source code (not in a subroutine because the bytecode cloning is shallow).
- The function will benefit from being compiled separately from other uses, for example because the way the clone will be called is expected to lead to a peculiar flow of control.
- The function refers to values in its closure environment, which the JIT will treat more like constants than variables.

See background information at [LuaJIT/LuaJIT#208](LuaJIT/LuaJIT#208).
This is an experimental optimization.

Call lib.specialize() on the pull and push method of each app instance.
Subject to certain other considerations this will cause each app
instance to have its own specially JITed machine code that can do nifty
things like compile configuration parameters as if they were constants.

Have to do some experimentation to better understand under which
circumstances this will be effective. (Can also be that the JIT has been
doing this for certain apps already.)
@eugeneia
Copy link
Member

This seems to trigger a bug visible in apps.vlan. Some edge case related to the shallow copying of functions?

wingo added a commit that referenced this pull request Apr 24, 2018
Flip sense of conditional-skip of IPsec end-to-end test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants