2018年4月1日日曜日

PostgreSQL11のJITコンパイリングを試す

llvm-postgres
開発中のPostgreSQL11でJIT(Just In Time=実行時)コンパイリングを行い、クエリ性能の高速化を期待する新機能が登場した。

本記事では

構築方法を確認したので紹介。JITコンパイリングを使いこなす話はまだ。

構築時のポイント

JITコンパイリングを有効にするためのPostgreSQL11導入方法や前提ライブラリを把握した。
  • 開発版PostgreSQLの最新のソースコードからコンパイルする
    • 前提ライブラリはllvmおよびclangの3.9.0以上
    • ./configure時に必要なオプションは--with-llvmLLVM_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-develzlib-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が得意な処理をちゃんと調べて、「こんなケースで効果がでる」みたいなところを明らかにしていきたい。

1 件のコメント:

  1. お疲れさまです。postgresql-11.2リリース版でやってみて、うまくゆきました。
    ※記事内に、psql コマンドの "set jit=on;" が書かれてませんでした。

    結果のExecution Timeですが、--★の値が、247360で35125.511 ms(JITなし)、247361で33995.024 ms(JITあり)でした。
    絶妙なサンプルクエリですね。

    返信削除

PostgreSQL11のJITコンパイリングを試す

llvm-postgres 開発中のPostgreSQL11でJIT(Just In Time=実行時)コンパイリングを行い、クエリ性能の高速化を期待する新機能が登場した。 本記事では 構築方法を確認したので紹介。JITコンパイ...