開発中のPostgreSQL11でJIT(Just In Time=実行時)コンパイリングを行い、クエリ性能の高速化を期待する新機能が登場した。
普通にepel-releaseからではllvm-3.4系がインストールされてしまうので追加のyumリポジトリを設定。
(本手順は stack overflow - How to install Clang and LLVM 3.9 on CentOS 7 を参考)
本稿ではここまで。
今後はJITが得意な処理をちゃんと調べて、「こんなケースで効果がでる」みたいなところを明らかにしていきたい。
本記事では
構築方法を確認したので紹介。JITコンパイリングを使いこなす話はまだ。構築時のポイント
JITコンパイリングを有効にするためのPostgreSQL11導入方法や前提ライブラリを把握した。- 開発版PostgreSQLの最新のソースコードからコンパイルする
- 前提ライブラリは
llvm
およびclang
の3.9.0以上 ./configure
時に必要なオプションは--with-llvm
、LLVM_CONFIG=<path>
、CLANG=<path>
の3つ
- 前提ライブラリは
- 構築時に遭遇するかもしれないエラーメッセージたち
出来上がった環境を見てみる
最低限のテストを行い、JITコンパイリング機能が発動するところまでを確認。- JIT無しで構築した環境との比較
- JITに関連すうる初期化パラメーター(postgresql.conf)を見てみる
- クエリの見積もりコストが一定以上でJITコンパイリングが発動
構築
手順1: llvmおよびclangのインストール
何度か構築作業のトライ&エラーしたところ、現在の最新dev版PostgreSQLは、configure時にLLVM-3.9.0以上を要求してくることが判明。まずはLLVMをインストールするところから。普通にepel-releaseからではllvm-3.4系がインストールされてしまうので追加のyumリポジトリを設定。
/* epel-releaseリポジトリを追加 */
# yum install epel-release
# yum update
/* 3.4系がlistされるが、PostgreSQL 11devでは3.9系以上が求められる */
# yum list | grep llvm
llvm.x86_64 3.4.2-8.el7 epel
llvm-devel.x86_64 3.4.2-8.el7 epel
:
epel-repoに以下を追加。(本手順は stack overflow - How to install Clang and LLVM 3.9 on CentOS 7 を参考)
# vi /etc/yum.repos.d/epel.repo
[alonid-llvm-3.9.0]
name=Copr repo for llvm-3.9.0 owned by alonid
baseurl=https://copr-be.cloud.fedoraproject.org/results/alonid/llvm-3.9.0/epel-7-x86_64/
type=rpm-md
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://copr-be.cloud.fedoraproject.org/results/alonid/llvm-3.9.0/pubkey.gpg
repo_gpgcheck=0
enabled=1
enabled_metadata=1
llvm-3.9.0をインストール# yum install llvm-3.9.0-devel
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: ftp.iij.ad.jp
* epel: www.ftp.ne.jp
* extras: ftp.iij.ad.jp
* updates: ftp.iij.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ llvm-3.9.0-devel.x86_64 0:3.9.0-7.el7.centos.alonid を インストール
--> 依存性の処理をしています: llvm-3.9.0(x86-64) = 3.9.0-7.el7.centos.alonid のパッケージ: llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libLLVM-3.9.so()(64bit) のパッケージ: llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ llvm-3.9.0.x86_64 0:3.9.0-7.el7.centos.alonid を インストール
---> パッケージ llvm-3.9.0-libs.x86_64 0:3.9.0-7.el7.centos.alonid を インストール
--> 依存性解決を終了しました。
依存性を解決しました
===============================================================================================================================================================================================================================================================================
Package アーキテクチャー バージョン リポジトリー 容量
===============================================================================================================================================================================================================================================================================
インストール中:
llvm-3.9.0-devel x86_64 3.9.0-7.el7.centos.alonid alonid-llvm-3.9.0 2.0 M
依存性関連でのインストールをします:
llvm-3.9.0 x86_64 3.9.0-7.el7.centos.alonid alonid-llvm-3.9.0 2.0 M
llvm-3.9.0-libs x86_64 3.9.0-7.el7.centos.alonid alonid-llvm-3.9.0 11 M
トランザクションの要約
===============================================================================================================================================================================================================================================================================
インストール 1 パッケージ (+2 個の依存関係のパッケージ)
総ダウンロード容量: 15 M
インストール容量: 58 M
Is this ok [y/d/N]: y
Downloading packages:
警告: /var/cache/yum/x86_64/7/alonid-llvm-3.9.0/packages/llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64.rpm: ヘッダー V3 RSA/SHA1 Signature、鍵 ID c7c0c111: NOKEY ] 289 kB/s | 384 kB 00:00:52 ETA
llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64.rpm の公開鍵がインストールされていません
(1/3): llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64.rpm | 2.0 MB 00:00:01
(2/3): llvm-3.9.0-3.9.0-7.el7.centos.alonid.x86_64.rpm | 2.0 MB 00:00:02
(3/3): llvm-3.9.0-libs-3.9.0-7.el7.centos.alonid.x86_64.rpm | 11 MB 00:00:03
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
合計 2.9 MB/s | 15 MB 00:00:05
https://copr-be.cloud.fedoraproject.org/results/alonid/llvm-3.9.0/pubkey.gpg から鍵を取得中です。
Importing GPG key 0xC7C0C111:
Userid : "alonid_llvm-3.9.0 (None) <alonid#llvm-3.9.0@copr.fedorahosted.org>"
Fingerprint: d6a8 1fa1 8ab0 d031 5b66 93fa 9455 6bf5 c7c0 c111
From : https://copr-be.cloud.fedoraproject.org/results/alonid/llvm-3.9.0/pubkey.gpg
上記の処理を行います。よろしいでしょうか? [y/N]y
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
インストール中 : llvm-3.9.0-libs-3.9.0-7.el7.centos.alonid.x86_64 1/3
インストール中 : llvm-3.9.0-3.9.0-7.el7.centos.alonid.x86_64 2/3
インストール中 : llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64 3/3
検証中 : llvm-3.9.0-3.9.0-7.el7.centos.alonid.x86_64 1/3
検証中 : llvm-3.9.0-libs-3.9.0-7.el7.centos.alonid.x86_64 2/3
検証中 : llvm-3.9.0-devel-3.9.0-7.el7.centos.alonid.x86_64 3/3
インストール:
llvm-3.9.0-devel.x86_64 0:3.9.0-7.el7.centos.alonid
依存性関連をインストールしました:
llvm-3.9.0.x86_64 0:3.9.0-7.el7.centos.alonid llvm-3.9.0-libs.x86_64 0:3.9.0-7.el7.centos.alonid
完了しました!
もう一つ、llvmに関連するclangの導入も必要。(最初に知っていればいきなりclangでも依存性解決してくれたのかも。)# yum install clang-3.9.0-devel
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: ftp.iij.ad.jp
* epel: mirror.dmmlabs.jp
* extras: ftp.iij.ad.jp
* updates: ftp.iij.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ clang-3.9.0-devel.x86_64 0:3.9.0-3.1.el7.centos.alonid を インストール
--> 依存性の処理をしています: clang-3.9.0(x86-64) = 3.9.0-3.1.el7.centos.alonid のパッケージ: clang-3.9.0-devel-3.9.0-3.1.el7.centos.alonid.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ clang-3.9.0.x86_64 0:3.9.0-3.1.el7.centos.alonid を インストール
--> 依存性の処理をしています: clang-3.9.0-libs(x86-64) = 3.9.0-3.1.el7.centos.alonid のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclang.so.3.9()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangAST.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangBasic.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangCodeGen.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangDriver.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangFormat.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangFrontend.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangFrontendTool.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangIndex.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangRewrite.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangRewriteFrontend.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangStaticAnalyzerFrontend.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangTooling.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> 依存性の処理をしています: libclangToolingCore.so()(64bit) のパッケージ: clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ clang-3.9.0-libs.x86_64 0:3.9.0-3.1.el7.centos.alonid を インストール
--> 依存性の処理をしています: compiler-rt-3.9.0(x86-64) >= 3.9.0 のパッケージ: clang-3.9.0-libs-3.9.0-3.1.el7.centos.alonid.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ compiler-rt-3.9.0.x86_64 0:3.9.0-3.el7.centos.alonid を インストール
--> 依存性解決を終了しました。
依存性を解決しました
===============================================================================================================================================================================================================================================================================
Package アーキテクチャー バージョン リポジトリー 容量
===============================================================================================================================================================================================================================================================================
インストール中:
clang-3.9.0-devel x86_64 3.9.0-3.1.el7.centos.alonid alonid-llvm-3.9.0 1.5 M
依存性関連でのインストールをします:
clang-3.9.0 x86_64 3.9.0-3.1.el7.centos.alonid alonid-llvm-3.9.0 441 k
clang-3.9.0-libs x86_64 3.9.0-3.1.el7.centos.alonid alonid-llvm-3.9.0 8.6 M
compiler-rt-3.9.0 x86_64 3.9.0-3.el7.centos.alonid alonid-llvm-3.9.0 1.4 M
トランザクションの要約
===============================================================================================================================================================================================================================================================================
インストール 1 パッケージ (+3 個の依存関係のパッケージ)
総ダウンロード容量: 12 M
インストール容量: 60 M
Is this ok [y/d/N]: y
Downloading packages:
(1/4): clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64.rpm | 441 kB 00:00:01
(2/4): clang-3.9.0-devel-3.9.0-3.1.el7.centos.alonid.x86_64.rpm | 1.5 MB 00:00:01
(3/4): compiler-rt-3.9.0-3.9.0-3.el7.centos.alonid.x86_64.rpm | 1.4 MB 00:00:00
(4/4): clang-3.9.0-libs-3.9.0-3.1.el7.centos.alonid.x86_64.rpm | 8.6 MB 00:00:02
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
合計 2.6 MB/s | 12 MB 00:00:04
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
インストール中 : compiler-rt-3.9.0-3.9.0-3.el7.centos.alonid.x86_64 1/4
インストール中 : clang-3.9.0-libs-3.9.0-3.1.el7.centos.alonid.x86_64 2/4
インストール中 : clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64 3/4
インストール中 : clang-3.9.0-devel-3.9.0-3.1.el7.centos.alonid.x86_64 4/4
検証中 : clang-3.9.0-3.9.0-3.1.el7.centos.alonid.x86_64 1/4
検証中 : compiler-rt-3.9.0-3.9.0-3.el7.centos.alonid.x86_64 2/4
検証中 : clang-3.9.0-devel-3.9.0-3.1.el7.centos.alonid.x86_64 3/4
検証中 : clang-3.9.0-libs-3.9.0-3.1.el7.centos.alonid.x86_64 4/4
インストール:
clang-3.9.0-devel.x86_64 0:3.9.0-3.1.el7.centos.alonid
依存性関連をインストールしました:
clang-3.9.0.x86_64 0:3.9.0-3.1.el7.centos.alonid clang-3.9.0-libs.x86_64 0:3.9.0-3.1.el7.centos.alonid compiler-rt-3.9.0.x86_64 0:3.9.0-3.el7.centos.alonid
完了しました!
導入したllvmおよびclangは/opt/llvm-3.9.0
ディレクトリ下に作成されていた。(3.9系のrpmでは各コマンドにパスが通っていなかったため、which
が使えなくていろいろ探した。)# cd /opt/llvm-3.9.0/
# ls
bin include lib64
# cd /opt/llvm-3.9.0/bin/
# ls
bugpoint clang++ clang-cl lli llvm-bcanalyzer llvm-cov llvm-dis llvm-dwp llvm-link llvm-mcmarkup llvm-pdbdump llvm-readobj llvm-split llvm-tblgen sancov yaml2obj
c-index-test clang-3.9 clang-format llvm-ar llvm-c-test llvm-cxxdump llvm-dsymutil llvm-extract llvm-lto llvm-nm llvm-profdata llvm-rtdyld llvm-stress obj2yaml sanstats
clang clang-check llc llvm-as llvm-config-64 llvm-diff llvm-dwarfdump llvm-lib llvm-mc llvm-objdump llvm-ranlib llvm-size llvm-symbolizer opt verify-uselistorder
PostgreSQLのconfigure時、llvm-config
コマンドおよびclang
コマンドのパスが必要になるので確認しておく。/* llvm-configコマンドでバージョンを確認(フルパスで実行できることを確認) */
# /opt/llvm-3.9.0/bin/llvm-config-64 --version
3.9.0
/* clangコマンドでバージョンを確認(フルパスで実行できることを確認) */
# /opt/llvm-3.9.0/bin/clang --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/llvm-3.9.0/bin
手順2: PostgreSQLのconfugreとインストール
PostgreSQLのソースからインストールしたことがある人は、configureオプションさえ気を付ければいつも通り。慣れていない方向けのもう少し詳しい手順は後述。configure
# cd /media/postgres-master/
# ./configure --prefix=/home/pg11/pg11-home-withllvm --with-llvm LLVM_CONFIG=/opt/llvm-3.9.0/bin/llvm-config-64 CLANG=/opt/llvm-3.9.0/bin/clang
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking which template to use... linux
:
make
# make
make -C src all
make[1]: ディレクトリ `/media/postgres-master/src' に入ります
make -C common all
:
All of PostgreSQL successfully made. Ready to install.
make install
# su pg11
# make install
make -C src install
make[1]: ディレクトリ `/media/postgres-master/src' に入ります
make -C common install
:
PostgreSQL installation complete.
インストール後の状態
pg11ユーザーにスイッチし、--prefix
で指定したディレクトリにインストールされていることを確認# su - pg11
$ ls
pg11-home-withllvm
$ ls -ltr ./pg11-home-withllvm/
合計 12
drwxrwxr-x. 3 pg11 pg11 23 3月 31 13:17 share
drwxrwxr-x. 4 pg11 pg11 4096 3月 31 13:18 include
drwxrwxr-x. 4 pg11 pg11 4096 3月 31 13:18 lib
drwxrwxr-x. 2 pg11 pg11 4096 3月 31 13:18 bin
$ ls ./pg11-home-withllvm/bin
clusterdb createuser dropuser initdb pg_basebackup pg_controldata pg_dump pg_isready pg_recvlogical pg_restore pg_test_fsync pg_upgrade pgbench postmaster reindexdb
createdb dropdb ecpg pg_archivecleanup pg_config pg_ctl pg_dumpall pg_receivewal pg_resetwal pg_rewind pg_test_timing pg_waldump postgres psql vacuumdb
$ ls ./pg11-home-withllvm/share
postgresql
$ ls ./pg11-home-withllvm/include
ecpg_config.h ecpgerrno.h ecpgtype.h libpq-events.h pg_config.h pg_config_manual.h pgtypes_date.h pgtypes_interval.h pgtypes_timestamp.h postgresql sqlca.h sqlda-native.h
ecpg_informix.h ecpglib.h libpq libpq-fe.h pg_config_ext.h pg_config_os.h pgtypes_error.h pgtypes_numeric.h postgres_ext.h sql3types.h sqlda-compat.h sqlda.h
$ ls ./pg11-home-withllvm/lib
libecpg.a libecpg.so.6 libecpg_compat.a libecpg_compat.so.3 libpgcommon.a libpgport.a libpgtypes.so libpgtypes.so.3.11 libpq.so libpq.so.5.11 postgresql
libecpg.so libecpg.so.6.11 libecpg_compat.so libecpg_compat.so.3.11 libpgfeutils.a libpgtypes.a libpgtypes.so.3 libpq.a libpq.so.5 pkgconfig
pg_config
コマンドで確認すると、CONFIGURE
行やLDFLAGS
行よりLLVM込みでインストールできていることを読み取ることができる。$ pg_config
BINDIR = /home/pg11/pg11-home-withllvm/bin
DOCDIR = /home/pg11/pg11-home-withllvm/share/doc/postgresql
HTMLDIR = /home/pg11/pg11-home-withllvm/share/doc/postgresql
INCLUDEDIR = /home/pg11/pg11-home-withllvm/include
PKGINCLUDEDIR = /home/pg11/pg11-home-withllvm/include/postgresql
INCLUDEDIR-SERVER = /home/pg11/pg11-home-withllvm/include/postgresql/server
LIBDIR = /home/pg11/pg11-home-withllvm/lib
PKGLIBDIR = /home/pg11/pg11-home-withllvm/lib/postgresql
LOCALEDIR = /home/pg11/pg11-home-withllvm/share/locale
MANDIR = /home/pg11/pg11-home-withllvm/share/man
SHAREDIR = /home/pg11/pg11-home-withllvm/share/postgresql
SYSCONFDIR = /home/pg11/pg11-home-withllvm/etc/postgresql
PGXS = /home/pg11/pg11-home-withllvm/lib/postgresql/pgxs/src/makefiles/pgxs.mk
CONFIGURE = '--prefix=/home/pg11/pg11-home-withllvm' '--with-llvm' 'LLVM_CONFIG=/opt/llvm-3.9.0/bin/llvm-config-64' 'CLANG=/opt/llvm-3.9.0/bin/clang'
CC = gcc
CPPFLAGS = -DFRONTEND -D_GNU_SOURCE
CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2
CFLAGS_SL = -fPIC
LDFLAGS = -L../../src/common -L/opt/llvm-3.9.0/lib64 -Wl,--as-needed -Wl,-rpath,'/home/pg11/pg11-home-withllvm/lib',--enable-new-dtags
LDFLAGS_EX =
LDFLAGS_SL =
LIBS = -lpgcommon -lpgport -lpthread -lz -lreadline -lrt -lcrypt -ldl -lm
VERSION = PostgreSQL 11devel
PostgerSQLインストールの補足
pg11ユーザー作成
今回はPostgreSQLをpg11ユーザーの所有でインストールする & インストール先ディレクトリをpg11ユーザーのホーム直下にしたくて事前にユーザーを作成。# useradd pg11
# su - pg11
$ pwd
/home/pg11
$ exit
#
最新版ソースコードの取得
上述の「configure」以降の手順は、以下の通り最新版のソースコードを取得したうえで、解凍したディレクトリ(~/postgres-master/)に移動して実行している。# cd /media
# wget https://github.com/postgres/postgres/archive/master.zip
# unzip master.zip
# cd /media/postgres-master/
# ls
COPYRIGHT GNUmakefile GNUmakefile.in HISTORY Makefile README README.git aclocal.m4 config config.log config.status configure configure.in contrib doc src
configure時のエラー
ありがちなエラーを整理(llvm関係ないものも含む。)- readline関連
- zlib関連
→それぞれreadline-devel
、zlib-devel
を事前に導入しておく
# yum install readline-devel
# yum install zlib-devel
- llvmのバージョン関連
→メッセージに従い、要求されているバージョンをなんとかして追加する
/* エラーメッセージの例 */
checking for llvm-config... /usr/bin/llvm-config
configure: error: /usr/bin/llvm-config version is 3.4.2 but at least 3.9 is required
- LLVM_CONFIG関連
- CLANG関連
→llvm_config
コマンドやclang
コマンドの正しいパスを確認して、LLVM_CONFIG
オプションまたはCLANG
オプションで指定。
/* エラーメッセージの例 */
checking for llvm-config... no
checking for llvm-config-6.0... no
checking for llvm-config-5.0... no
checking for llvm-config-4.0... no
checking for llvm-config-3.9... no
configure: error: llvm-config not found, but required when compiling --with-llvm, specify with LLVM_CONFIG=
/* エラーメッセージの例 */
checking for LLVM_CONFIG... /opt/llvm-3.9.0/bin/llvm-config-64
checking for clang... no
checking for clang-6.0... no
checking for clang-5.0... no
checking for clang-4.0... no
checking for clang-3.9... no
configure: error: clang not found, but required when compiling --with-llvm, specify with CLANG=
本稿のために実行時のログを整理していて、LLVMやCLANGのバージョンが3.9指定ではなく、もっと新しいもの(6.0や5.0など)であれば、PostgreSQLがちゃんと探して使ってくれるのだな・・・と気づいた。新しいほうが賢かったりするんだろうか。出来上がった環境を見る
llvm無しで作った環境と比較
LLVMサポートのために追加されたファイル
<path-to-postgres>/lib/postgresql
配下に以下のファイル・ディレクトリが追加されている。$ cd lib/postgresql/
$ ls -ltr
drwxrwxr-x. 3 1002 1002 45 3月 31 13:18 bitcode
-rwxr-xr-x. 1 1002 1002 138560 3月 31 13:18 llvmjit.so
-rw-r--r--. 1 1002 1002 6044 3月 31 13:18 llvmjit_types.bc
(その他は省略)
ファイルサイズ。ノーマルのPostgreSQLに対して結構でかい。/* 追加されたファイルが15MB強 */
$ du -sh ./pg11-home-withllvm/lib/postgresql/*
15M ./bitcode
136K ./llvmjit.so
8.0K ./llvmjit_types.bc
(その他は省略)
/* PostgreSQLのインストール先全体の約25MBに対して、15MBほど追加されて計40MB程度になる。*/
$ du -sh ./pg11-home-withllvm/*
12M ./pg11-home-withllvm/bin
6.1M ./pg11-home-withllvm/include
20M ./pg11-home-withllvm/lib
2.9M ./pg11-home-withllvm/share
$ du -sh ./pg11-home-nollvm/*
12M ./pg11-home-nollvm/bin
6.1M ./pg11-home-nollvm/include
4.6M ./pg11-home-nollvm/lib
2.9M ./pg11-home-nollvm/share
ちなみにbitcode
ディレクトリ配下はたくさんのLLVM Bitcodeが配置されている。$ cd ./pg11-home-withllvm/lib/postgresql
$ ls
ascii_and_mic.so dict_snowball.so euc_jp_and_sjis.so latin2_and_win1250.so llvmjit.so pgxs utf8_and_big5.so utf8_and_euc_cn.so utf8_and_euc_tw.so utf8_and_iso8859.so utf8_and_sjis.so utf8_and_win.so
bitcode euc2004_sjis2004.so euc_kr_and_mic.so latin_and_mic.so llvmjit_types.bc plpgsql.so utf8_and_cyrillic.so utf8_and_euc_jp.so utf8_and_gb18030.so utf8_and_iso8859_1.so utf8_and_sjis2004.so
cyrillic_and_mic.so euc_cn_and_mic.so euc_tw_and_big5.so libpqwalreceiver.so pgoutput.so utf8_and_ascii.so utf8_and_euc2004.so utf8_and_euc_kr.so utf8_and_gbk.so utf8_and_johab.so utf8_and_uhc.so
$ cd bitcode
$ ls
postgres postgres.index.bc
$ cd postgres
$ ls
access bootstrap catalog commands executor foreign jit lib libpq main nodes optimizer parser port postmaster regex replication rewrite statistics storage tcop tsearch utils
$ cd executor
$ ls
execAmi.bc execIndexing.bc execProcnode.bc execUtils.bc nodeBitmapAnd.bc nodeCustom.bc nodeGroup.bc nodeLimit.bc nodeModifyTable.bc nodeResult.bc nodeSubplan.bc nodeValuesscan.bc tstoreReceiver.bc
execCurrent.bc execJunk.bc execReplication.bc functions.bc nodeBitmapHeapscan.bc nodeForeignscan.bc nodeHash.bc nodeLockRows.bc nodeNamedtuplestorescan.bc nodeSamplescan.bc nodeSubqueryscan.bc nodeWindowAgg.bc
execExpr.bc execMain.bc execSRF.bc instrument.bc nodeBitmapIndexscan.bc nodeFunctionscan.bc nodeHashjoin.bc nodeMaterial.bc nodeNestloop.bc nodeSeqscan.bc nodeTableFuncscan.bc nodeWorktablescan.bc
execExprInterp.bc execParallel.bc execScan.bc nodeAgg.bc nodeBitmapOr.bc nodeGather.bc nodeIndexonlyscan.bc nodeMergeAppend.bc nodeProjectSet.bc nodeSetOp.bc nodeTidscan.bc spi.bc
execGrouping.bc execPartition.bc execTuples.bc nodeAppend.bc nodeCtescan.bc nodeGatherMerge.bc nodeIndexscan.bc nodeMergejoin.bc nodeRecursiveunion.bc nodeSort.bc nodeUnique.bc tqueue.bc
使ってみる
環境変数の設定
最低限、.bash_profileにこれぐらい追加しておけば良い。今回は複数の環境で違いを見くらべたいのでこんな感じに環境変数設定ファイルを都度読むようにする。$ cp .bash_profile .withllvm_profile
$ vi .withllvm_profile
export PGHOME=$HOME/pg11-home-withllvm
export PGDATA=$HOME/data-withllvm
export PGPORT=5435
export PGDATABASE=postgres
export PATH=$PGHOME/bin:.:$PATH
こっちのファイルを反映するときはsource
で読みこむ。$ source .withllvm_profile
initdb
JITサポートのためのinitdbオプションも探したがそのようなものはない。普通initdbすればOK。$ initdb -E utf8 --no-locale
The files belonging to this database system will be owned by user "pg11".
This user must also own the server process.
The database cluster will be initialized with locale "C".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /home/pg11/data-withllvm ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
pg_ctl -D /home/pg11/data-withllvm -l logfile start
データディレクトリが作成された。$ cd $PGDATA
$ pwd
/home/pg11/data-withllvm
$ ls
PG_VERSION base global pg_commit_ts pg_dynshmem pg_hba.conf pg_ident.conf pg_logical pg_multixact pg_notify pg_replslot pg_serial pg_snapshots pg_stat pg_stat_tmp pg_subtrans pg_tblspc pg_twophase pg_wal pg_xact postgresql.auto.conf postgresql.conf
設定ファイルの編集&起動
-
postgresql.confでは以下のパラメーターを修正
- listen_addresses = ‘*’
- port = 5435
- logging_collector = on
-
pg_hba.confは以下
- 自分のノートPCのIPアドレスを許可
データベース起動
$ pg_ctl start
パラメーター一覧からjitを検索
postgres=# SELECT name,setting,context,category,short_desc,extra_desc FROM pg_settings WHERE name LIKE '%jit%' ORDER BY category DESC,name ASC;
name | setting | context | category | short_desc | extra_desc
-------------------------+---------+-------------------+---------------------------------------+------------------------------------------------------+------------------------------
jit_above_cost | 100000 | user | Query Tuning / Planner Cost Constants | Perform JIT compilation if query is more expensive. | -1 disables JIT compilation.
jit_inline_above_cost | 500000 | user | Query Tuning / Planner Cost Constants | Perform JIT inlining if query is more expensive. | -1 disables inlining.
jit_optimize_above_cost | 500000 | user | Query Tuning / Planner Cost Constants | Optimize JITed functions if query is more expensive. | -1 disables optimization.
jit | on | user | Query Tuning / Other Planner Options | Allow JIT compilation. |
jit_provider | llvmjit | postmaster | File Locations | JIT provider to use. |
jit_debugging_support | off | superuser-backend | Developer Options | Register JIT compiled function with debugger. |
jit_dump_bitcode | off | superuser | Developer Options | Write out LLVM bitcode to facilitate JIT debugging. |
jit_expressions | on | user | Developer Options | Allow JIT compilation of expressions. |
jit_profiling_support | off | superuser-backend | Developer Options | Register JIT compiled function with perf profiler. |
jit_tuple_deforming | on | user | Developer Options | Allow JIT compilation of tuple deforming. |
(10 rows)
注意: LLVM無しで作った環境もパラメーター自体は同じものが設定されていた。JITが発動するとどうなるか
クエリの見積もりコストがjit_above_cost
を超えると発動するとのことなので、pgbenchのテーブルを使って超雑にコストの高いクエリを作ってみた。複雑にしたいがために適当of適当で作った。クエリの意味を考えてはいけない。/* サンプルはpgbenchのテーブルで */
$ pgbench -i -s 100 -U bench bench
creating tables...
generating data...
100000 of 10000000 tuples (1%) done (elapsed 0.23 s, remaining 23.10 s)
200000 of 10000000 tuples (2%) done (elapsed 0.48 s, remaining 23.76 s)
:
done.
/* pgbenchのベンチマークではなく、無駄に重く作ってみたクエリ。★の行数でコストが変わる。 */
EXPLAIN ANALYZE
WITH a AS (SELECT a.aid,abalance,b.bid,tbalance FROM pgbench_accounts a
JOIN pgbench_branches b ON a.bid=b.bid
JOIN pgbench_tellers t ON b.bid = t.bid
WHERE a.aid between 50000 and xxxxxx) --★
SELECT * FROM pgbench_branches
RIGHT OUTER JOIN a ON pgbench_branches.bbalance = tbalance
WHERE tbalance % 35 in (0,2,5,7,9,11,13,17);
★を調整して、見積もりコスト(1行目のHash Left Join (cost=33360.21..100000.04
)が100000を超えると、JITが発動した。bench=> explain analyze with A as (select a.aid,abalance,b.bid,tbalance from pgbench_accounts a join pgbench_branches b on a.bid=b.bid JOIN pgbench_tellers t ON b.bid = t.bid
WHERE a.aid between 50000 and 262926) -- ★
select * from pgbench_branches right outer join A on pgbench_branches.bbalance = tbalance where tbalance % 35 in (0,2,5,7,9,11,13,17);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Hash Left Join (cost=33360.21..100000.04 rows=81144 width=380) (actual time=45.816..3774.989 rows=212927 loops=1)
Hash Cond: (a.tbalance = pgbench_branches.bbalance)
CTE a
-> Hash Join (cost=49.72..33355.96 rows=2028610 width=16) (actual time=45.637..1518.676 rows=2129270 loops=1)
Hash Cond: (a_1.bid = b.bid)
-> Index Scan using pgbench_accounts_pkey on pgbench_accounts a_1 (cost=0.43..9977.66 rows=202861 width=12) (actual time=0.076..207.748 rows=212927 loops=1)
Index Cond: ((aid >= 50000) AND (aid <= 262926))
-> Hash (cost=36.79..36.79 rows=1000 width=12) (actual time=45.497..45.497 rows=1000 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 51kB
-> Hash Join (cost=4.25..36.79 rows=1000 width=12) (actual time=43.046..44.835 rows=1000 loops=1)
Hash Cond: (t.bid = b.bid)
-> Seq Scan on pgbench_tellers t (cost=0.00..20.00 rows=1000 width=8) (actual time=0.041..0.610 rows=1000 loops=1)
-> Hash (cost=3.00..3.00 rows=100 width=4) (actual time=42.934..42.934 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 12kB
-> Seq Scan on pgbench_branches b (cost=0.00..3.00 rows=100 width=4) (actual time=42.699..42.805 rows=100 loops=1)
-> CTE Scan on a (cost=0.00..65929.82 rows=81144 width=16) (actual time=45.665..3541.279 rows=212927 loops=1)
Filter: ((tbalance % 35) = ANY ('{0,2,5,7,9,11,13,17}'::integer[]))
Rows Removed by Filter: 1916343
-> Hash (cost=3.00..3.00 rows=100 width=364) (actual time=0.122..0.122 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 12kB
-> Seq Scan on pgbench_branches (cost=0.00..3.00 rows=100 width=364) (actual time=0.011..0.058 rows=100 loops=1)
Planning Time: 1.694 ms
JIT:
Functions: 36
Generation Time: 11.757 ms
Inlining: false
Inlining Time: 0.000 ms
Optimization: false
Optimization Time: 2.401 ms
Emission Time: 39.496 ms
Execution Time: 3894.130 ms
(31 rows)
Time: 3903.549 ms (00:03.904)
試しに★を1行へらして、コストが100000を下回ると、JITは発動しない。bench=> explain analyze with A as (select a.aid,abalance,b.bid,tbalance from pgbench_accounts a join pgbench_branches b on a.bid=b.bid JOIN pgbench_tellers t ON b.bid = t.bid
WHERE a.aid between 50000 and 262925) -- ★
select * from pgbench_branches right outer join A on pgbench_branches.bbalance = tbalance where tbalance % 35 in (0,2,5,7,9,11,13,17);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Hash Left Join (cost=33360.07..99999.58 rows=81144 width=380) (actual time=3.699..3824.800 rows=212926 loops=1)
Hash Cond: (a.tbalance = pgbench_branches.bbalance)
CTE a
-> Hash Join (cost=49.72..33355.82 rows=2028600 width=16) (actual time=3.499..1532.521 rows=2129260 loops=1)
Hash Cond: (a_1.bid = b.bid)
-> Index Scan using pgbench_accounts_pkey on pgbench_accounts a_1 (cost=0.43..9977.64 rows=202860 width=12) (actual time=0.054..201.977 rows=212926 loops=1)
Index Cond: ((aid >= 50000) AND (aid <= 262925))
-> Hash (cost=36.79..36.79 rows=1000 width=12) (actual time=3.411..3.411 rows=1000 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 51kB
-> Hash Join (cost=4.25..36.79 rows=1000 width=12) (actual time=1.076..2.791 rows=1000 loops=1)
Hash Cond: (t.bid = b.bid)
-> Seq Scan on pgbench_tellers t (cost=0.00..20.00 rows=1000 width=8) (actual time=0.023..0.613 rows=1000 loops=1)
-> Hash (cost=3.00..3.00 rows=100 width=4) (actual time=1.024..1.024 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 12kB
-> Seq Scan on pgbench_branches b (cost=0.00..3.00 rows=100 width=4) (actual time=0.005..0.085 rows=100 loops=1)
-> CTE Scan on a (cost=0.00..65929.50 rows=81144 width=16) (actual time=3.520..3594.655 rows=212926 loops=1)
Filter: ((tbalance % 35) = ANY ('{0,2,5,7,9,11,13,17}'::integer[]))
Rows Removed by Filter: 1916334
-> Hash (cost=3.00..3.00 rows=100 width=364) (actual time=0.130..0.130 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 12kB
-> Seq Scan on pgbench_branches (cost=0.00..3.00 rows=100 width=364) (actual time=0.009..0.056 rows=100 loops=1)
Planning Time: 1.282 ms
Execution Time: 3931.001 ms
(23 rows)
Time: 3935.137 ms (00:03.935)
と、パラメーターの設定にしたがってJITが発動している様子がわかります。本稿ではここまで。
今後はJITが得意な処理をちゃんと調べて、「こんなケースで効果がでる」みたいなところを明らかにしていきたい。