As you might already know PostgreSQL 11 will bring support for just-in-time compilation. When you want to compile PostgreSQL 11 with jit support on RedHat/CentOS 7 this requires a little hack (more on the reason below). In this post we’ll look at how you can do it at least for testing. For production it is of course not recommended as hacking the make file is nothing you want to do, at least I would not do it. Lets go.
As mentioned I am on CentOS 7:
1 2 | postgres@pgbox:$ cat /etc/centos-release CentOS Linux release 7.5.1804 (Core) |
What you need to get support for jit is llvm. When you check the CentOS repository llvm is there:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | postgres@pgbox:$ yum search llvm Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirror.spreitzer.ch * extras: mirror.spreitzer.ch * updates: mirror.spreitzer.ch ===================================================== N /S matched: llvm ===================================================== llvm-devel.x86_64 : Libraries and header files for LLVM llvm-doc.noarch : Documentation for LLVM llvm-libs.x86_64 : LLVM shared libraries llvm-ocaml.x86_64 : OCaml binding for LLVM llvm-ocaml-devel.x86_64 : Development files for llvm-ocaml llvm-ocaml-doc.noarch : Documentation for LLVM's OCaml binding llvm-private.i686 : llvm engine for Mesa llvm-private.x86_64 : llvm engine for Mesa llvm-private-devel.i686 : Libraries and header files for LLVM llvm-private-devel.x86_64 : Libraries and header files for LLVM llvm-static.x86_64 : LLVM static libraries mesa-private-llvm.i686 : llvm engine for Mesa mesa-private-llvm.x86_64 : llvm engine for Mesa mesa-private-llvm-devel.i686 : Libraries and header files for LLVM mesa-private-llvm-devel.x86_64 : Libraries and header files for LLVM clang.x86_64 : A C language family front-end for LLVM llvm.x86_64 : The Low Level Virtual Machine Name and summary matches only, use "search all" for everything. |
The issue is that the PostgreSQL documentation clearly states that llvm needs to be at least of version 3.9 and in the CentOS repository you’ll find this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | postgres@pgbox:$ yum info llvm Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirror1.hs-esslingen.de * extras: mirror.fra10.de.leaseweb.net * updates: mirror.netcologne.de Available Packages Name : llvm Arch : x86_64 Version : 3.4.2 Release : 8.el7 Size : 1.3 M Repo : extras/7/x86_64 Summary : The Low Level Virtual Machine URL : http://llvm.org/ License : NCSA Description : LLVM is a compiler infrastructure designed for compile- time , : link- time , runtime, and idle- time optimization of programs from : arbitrary programming languages. The compiler infrastructure includes : mirror sets of programming tools as well as libraries with equivalent : functionality. |
What to do? What you need to do is to add the epel repository where you can find llvm 3.9 and 5.0:
1 2 3 | postgres@pgbox:$ wget http: //dl .fedoraproject.org /pub/epel/epel-release-latest-7 .noarch.rpm postgres@pgbox:$ sudo yum localinstall epel-release-latest-7.noarch.rpm postgres@pgbox:$ sudo yum install llvm5.0 llvm5.0-devel clang |
Having that we should be ready for configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | postgres@pgbox:$ PGHOME= /u01/app/postgres/product/11/db_0 postgres@pgbox:$ SEGSIZE=1 postgres@pgbox:$ BLOCKSIZE=8 postgres@pgbox:$ WALSEGSIZE=16 postgres@pgbox:$ . /configure --prefix=${PGHOME} -- exec -prefix=${PGHOME} --bindir=${PGHOME} /bin --libdir=${PGHOME} /lib --sysconfdir=${PGHOME} /etc --includedir=${PGHOME} /include --datarootdir=${PGHOME} /share --datadir=${PGHOME} /share --with-pgport=5432 --with-perl --with-python --with-openssl --with-pam --with-ldap --with-libxml --with-libxslt --with-segsize=${SEGSIZE} --with-blocksize=${BLOCKSIZE} --with-wal-segsize=${WALSEGSIZE} --with-llvm LLVM_CONFIG= '/usr/lib64/llvm3.9/bin/llvm-config' --with-systemd |
That succeeds so lets compile:
1 | postgres@pgbox:$ make -j 4 all |
… and you will run into this issue:
1 2 3 4 5 6 7 | /usr/bin/clang -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -O2 -I../.. /src/include -D_GNU_SOURCE -flto=thin -emit-llvm -c -o localtime. bc localtime.c clang: error: unknown argument: '-flto=thin' make [2]: *** [localtime. bc ] Error 1 make [2]: Leaving directory ` /home/postgres/postgresql/src/timezone ' make [1]: *** [all-timezone-recurse] Error 2 make [1]: Leaving directory ` /home/postgres/postgresql/src ' make : *** [all-src-recurse] Error 2 |
There is a mail thread on the hackers mailing list which describes the issue. Apparently the clang compiler is too old to understand this argument. What you could do is to adjust the corresponding line in the Makefile:
1 2 3 | postgres@pgbox:$ vi src /Makefile .global. in COMPILE.c. bc = $(CLANG) -Wno-ignored-attributes $(BITCODE_CFLAGS) $(CPPFLAGS) -flto=thin -emit-llvm -c COMPILE.c. bc = $(CLANG) -Wno-ignored-attributes $(BITCODE_CFLAGS) $(CPPFLAGS) -emit-llvm -c |
Doing all the stuff again afterwards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | postgres@pgbox:$ make clean postgres@pgbox:$ . /configure --prefix=${PGHOME} -- exec -prefix=${PGHOME} --bindir=${PGHOME} /bin --libdir=${PGHOME} /lib --sysconfdir=${PGHOME} /etc --includedir=${PGHOME} /include --datarootdir=${PGHOME} /share --datadir=${PGHOME} /share --with-pgport=5432 --with-perl --with-python --with-openssl --with-pam --with-ldap --with-libxml --with-libxslt --with-segsize=${SEGSIZE} --with-blocksize=${BLOCKSIZE} --with-wal-segsize=${WALSEGSIZE} --with-llvm LLVM_CONFIG= '/usr/lib64/llvm3.9/bin/llvm-config' --with-systemd postgres@pgbox:$ make -j 4 all |
… led to the following issue (at least for me):
1 2 3 4 5 6 7 | make [2]: g++: Command not found make [2]: *** [llvmjit_error.o] Error 127 make [2]: *** Waiting for unfinished jobs.... make [2]: Leaving directory ` /home/postgres/postgresql/src/backend/jit/llvm ' make [1]: *** [all-backend /jit/llvm-recurse ] Error 2 make [1]: Leaving directory ` /home/postgres/postgresql/src ' make : *** [all-src-recurse] Error 2 |
This should be easy to fix:
1 2 3 | postgres@pgbox:$ sudo yum install -y gcc -c++ postgres@pgbox:$ which g++ /bin/g ++ |
Again:
1 2 3 | postgres@pgbox:$ make -j 4 install postgres@pgbox:$ cd contrib postgres@pgbox:$ make -j 4 install |
… and this time it succeeds (note that I did not run the regression tests, so maybe something will still go wrong there).
JIT is enabled by default and controlled by these parameters:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | postgres=# select name ,setting from pg_settings where name like 'jit%' ; name | setting -------------------------+--------- jit | on jit_above_cost | 100000 jit_debugging_support | off jit_dump_bitcode | off jit_expressions | on jit_inline_above_cost | 500000 jit_optimize_above_cost | 500000 jit_profiling_support | off jit_provider | llvmjit jit_tuple_deforming | on (10 rows ) |
To test that it really kicks in you can do something like this:
1 2 3 4 5 6 7 8 | postgres=# create table ttt (a int , b text, c date ); postgres=# insert into ttt (a,b,c) select aa.*, md5(aa::text), now() from generate_series(1,1000000) aa; postgres=# set jit_above_cost=5; postgres=# set jit_optimize_above_cost=5; postgres=# set jit_inline_above_cost=5; postgres=#explain select sum (a) from ttt; |
… which should lead to a plan like this:
1 2 3 4 5 6 7 8 9 10 11 12 | QUERY PLAN --------------------------------------------------------------------------------------- Finalize Aggregate (cost=15554.55..15554.56 rows =1 width=8) -> Gather (cost=15554.33..15554.54 rows =2 width=8) Workers Planned: 2 -> Partial Aggregate (cost=14554.33..14554.34 rows =1 width=8) -> Parallel Seq Scan on ttt (cost=0.00..13512.67 rows =416667 width=4) JIT: Functions: 8 Inlining: true Optimization: true (9 rows ) |
Hope that helps.