@@ -13,20 +13,20 @@ the CPU that just handles that expression, yielding a speedup.
1313That this is done at query execution time, possibly even only in cases
1414the relevant task is done a number of times, makes it JIT, rather than
1515ahead-of-time (AOT). Given the way JIT compilation is used in
16- postgres , the lines between interpretation, AOT and JIT are somewhat
16+ PostgreSQL , the lines between interpretation, AOT and JIT are somewhat
1717blurry.
1818
1919Note that the interpreted program turned into a native program does
2020not necessarily have to be a program in the classical sense. E.g. it
21- is highly beneficial JIT compile tuple deforming into a native
21+ is highly beneficial to JIT compile tuple deforming into a native
2222function just handling a specific type of table, despite tuple
2323deforming not commonly being understood as a "program".
2424
2525
2626Why JIT?
2727========
2828
29- Parts of postgres are commonly bottlenecked by comparatively small
29+ Parts of PostgreSQL are commonly bottlenecked by comparatively small
3030pieces of CPU intensive code. In a number of cases that is because the
3131relevant code has to be very generic (e.g. handling arbitrary SQL
3232level expressions, over arbitrary tables, with arbitrary extensions
@@ -49,11 +49,11 @@ particularly beneficial for removing branches during tuple deforming.
4949How to JIT
5050==========
5151
52- Postgres , by default, uses LLVM to perform JIT. LLVM was chosen
52+ PostgreSQL , by default, uses LLVM to perform JIT. LLVM was chosen
5353because it is developed by several large corporations and therefore
5454unlikely to be discontinued, because it has a license compatible with
55- PostgreSQL, and because its LLVM IR can be generated from C
56- using the clang compiler.
55+ PostgreSQL, and because its IR can be generated from C using the Clang
56+ compiler.
5757
5858
5959Shared Library Separation
@@ -68,22 +68,22 @@ An additional benefit of doing so is that it is relatively easy to
6868evaluate JIT compilation that does not use LLVM, by changing out the
6969shared library used to provide JIT compilation.
7070
71- To achieve this code, e.g. expression evaluation, intending to perform
72- JIT, calls a LLVM independent wrapper located in jit.c to do so. If
73- the shared library providing JIT support can be loaded (i.e. postgres
74- was compiled with LLVM support and the shared library is installed),
75- the task of JIT compiling an expression gets handed of to shared
76- library. This obviously requires that the function in jit.c is allowed
77- to fail in case no JIT provider can be loaded.
71+ To achieve this, code intending to perform JIT ( e.g. expression evaluation)
72+ calls an LLVM independent wrapper located in jit.c to do so. If the
73+ shared library providing JIT support can be loaded (i.e. PostgreSQL was
74+ compiled with LLVM support and the shared library is installed), the task
75+ of JIT compiling an expression gets handed off to the shared library. This
76+ obviously requires that the function in jit.c is allowed to fail in case
77+ no JIT provider can be loaded.
7878
7979Which shared library is loaded is determined by the jit_provider GUC,
8080defaulting to "llvmjit".
8181
8282Cloistering code performing JIT into a shared library unfortunately
8383also means that code doing JIT compilation for various parts of code
8484has to be located separately from the code doing so without
85- JIT. E.g. the JITed version of execExprInterp.c is located in
86- jit/llvm/ rather than executor/.
85+ JIT. E.g. the JIT version of execExprInterp.c is located in jit/llvm/
86+ rather than executor/.
8787
8888
8989JIT Context
@@ -105,9 +105,9 @@ implementations.
105105
106106Emitting individual functions separately is more expensive than
107107emitting several functions at once, and emitting them together can
108- provide additional optimization opportunities. To facilitate that the
109- LLVM provider separates function definition from emitting them in an
110- executable way .
108+ provide additional optimization opportunities. To facilitate that, the
109+ LLVM provider separates defining functions from optimizing and
110+ emitting functions in an executable manner .
111111
112112Creating functions into the current mutable module (a module
113113essentially is LLVM's equivalent of a translation unit in C) is done
@@ -127,7 +127,7 @@ used.
127127Error Handling
128128--------------
129129
130- There are two aspects to error handling. Firstly, generated (LLVM IR)
130+ There are two aspects of error handling. Firstly, generated (LLVM IR)
131131and emitted functions (mmap()ed segments) need to be cleaned up both
132132after a successful query execution and after an error. This is done by
133133registering each created JITContext with the current resource owner,
@@ -140,12 +140,12 @@ cleaning up emitted code upon ERROR, but there's also the chance that
140140LLVM itself runs out of memory. LLVM by default does *not* use any C++
141141exceptions. Its allocations are primarily funneled through the
142142standard "new" handlers, and some direct use of malloc() and
143- mmap(). For the former a 'new handler' exists
144- http://en.cppreference.com/w/cpp/memory/new/set_new_handler for the
145- latter LLVM provides callback that get called upon failure
146- (unfortunately mmap() failures are treated as fatal rather than OOM
147- errors). What we've, for now, chosen to do, is to have two functions
148- that LLVM using code must use:
143+ mmap(). For the former a 'new handler' exists:
144+ http://en.cppreference.com/w/cpp/memory/new/set_new_handler
145+ For the latter LLVM provides callbacks that get called upon failure
146+ (unfortunately mmap() failures are treated as fatal rather than OOM errors).
147+ What we've chosen to do for now is have two functions that LLVM using code
148+ must use:
149149extern void llvm_enter_fatal_on_oom(void);
150150extern void llvm_leave_fatal_on_oom(void);
151151before interacting with LLVM code.
@@ -160,31 +160,31 @@ the handlers instead are reset on toplevel sigsetjmp() level.
160160
161161Using a relatively small enter/leave protected section of code, rather
162162than setting up these handlers globally, avoids negative interactions
163- with extensions that might use C++ like e.g. postgis . As LLVM code
163+ with extensions that might use C++ such as PostGIS . As LLVM code
164164generation should never execute arbitrary code, just setting these
165165handlers temporarily ought to suffice.
166166
167167
168168Type Synchronization
169169--------------------
170170
171- To able to generate code performing tasks that are done in "interpreted"
172- postgres , it obviously is required that code generation knows about at
173- least a few postgres types. While it is possible to inform LLVM about
171+ To be able to generate code that can perform tasks done by "interpreted"
172+ PostgreSQL , it obviously is required that code generation knows about at
173+ least a few PostgreSQL types. While it is possible to inform LLVM about
174174type definitions by recreating them manually in C code, that is failure
175175prone and labor intensive.
176176
177177Instead there is one small file (llvmjit_types.c) which references each of
178178the types required for JITing. That file is translated to bitcode at
179179compile time, and loaded when LLVM is initialized in a backend.
180180
181- That works very well to synchronize the type definition, unfortunately
181+ That works very well to synchronize the type definition, but unfortunately
182182it does *not* synchronize offsets as the IR level representation doesn't
183- know field names. Instead required offsets are maintained as defines in
184- the original struct definition. E.g.
183+ know field names. Instead, required offsets are maintained as defines in
184+ the original struct definition, like so:
185185#define FIELDNO_TUPLETABLESLOT_NVALID 9
186186 int tts_nvalid; /* # of valid values in tts_values */
187- while that still needs to be defined, it's only required for a
187+ While that still needs to be defined, it's only required for a
188188relatively small number of fields, and it's bunched together with the
189189struct definition, so it's easily kept synchronized.
190190
@@ -193,12 +193,12 @@ Inlining
193193--------
194194
195195One big advantage of JITing expressions is that it can significantly
196- reduce the overhead of postgres 's extensible function/operator
197- mechanism, by inlining the body of called functions / operators.
196+ reduce the overhead of PostgreSQL 's extensible function/operator
197+ mechanism, by inlining the body of called functions/ operators.
198198
199199It obviously is undesirable to maintain a second implementation of
200200commonly used functions, just for inlining purposes. Instead we take
201- advantage of the fact that the clang compiler can emit LLVM IR.
201+ advantage of the fact that the Clang compiler can emit LLVM IR.
202202
203203The ability to do so allows us to get the LLVM IR for all operators
204204(e.g. int8eq, float8pl etc), without maintaining two copies. These
@@ -225,7 +225,7 @@ Caching
225225Currently it is not yet possible to cache generated functions, even
226226though that'd be desirable from a performance point of view. The
227227problem is that the generated functions commonly contain pointers into
228- per-execution memory. The expression evaluation functionality needs to
228+ per-execution memory. The expression evaluation machinery needs to
229229be redesigned a bit to avoid that. Basically all per-execution memory
230230needs to be referenced as an offset to one block of memory stored in
231231an ExprState, rather than absolute pointers into memory.
@@ -278,7 +278,7 @@ Currently there are a number of GUCs that influence JITing:
278278- jit_inline_above_cost = -1, 0-DBL_MAX - inlining is tried if query has
279279 higher cost.
280280
281- whenever a query's total cost is above these limits, JITing is
281+ Whenever a query's total cost is above these limits, JITing is
282282performed.
283283
284284Alternative costing models, e.g. by generating separate paths for
@@ -291,5 +291,5 @@ individual expressions.
291291The obvious seeming approach of JITing expressions individually after
292292a number of execution turns out not to work too well. Primarily
293293because emitting many small functions individually has significant
294- overhead. Secondarily because the time till JITing occurs causes
294+ overhead. Secondarily because the time until JITing occurs causes
295295relative slowdowns that eat into the gain of JIT compilation.
0 commit comments