CentOS6.5で async profiling する方法

yum を vault.centos.org に切り替え

前提

  • OS: CentOS 6.10(VM)
  • root で作業
  • ネットに出られる前提
cd /etc/yum.repos.d
mkdir backup
mv *.repo backup/

cat > /etc/yum.repos.d/CentOS-Vault-6.10.repo << 'EOF'
[base]
name=CentOS-6.10 - Base
baseurl=http://vault.centos.org/6.10/os/$basearch/
gpgcheck=0
enabled=1

[updates]
name=CentOS-6.10 - Updates
baseurl=http://vault.centos.org/6.10/updates/$basearch/
gpgcheck=0
enabled=1

[extras]
name=CentOS-6.10 - Extras
baseurl=http://vault.centos.org/6.10/extras/$basearch/
gpgcheck=0
enabled=1
EOF

yum clean all
yum makecache

SCL(Software Collections)と devtoolset-7 の導入

SCL 用 repo を vault 向きに作成

cat > /etc/yum.repos.d/CentOS-SCLo-scl.repo << 'EOF'
[centos-sclo-sclo]
name=CentOS-6.10 - SCLo sclo
baseurl=http://vault.centos.org/6.10/sclo/x86_64/sclo/
gpgcheck=0
enabled=1
EOF

cat > /etc/yum.repos.d/CentOS-SCLo-rh.repo << 'EOF'
[centos-sclo-rh]
name=CentOS-6.10 - SCLo rh
baseurl=http://vault.centos.org/6.10/sclo/x86_64/rh/
gpgcheck=0
enabled=1
EOF

yum clean all
yum makecache

devtoolset-7 をインストール

yum install devtoolset-7

使用するシェルを devtoolset-7 に切り替え

scl enable devtoolset-7 bash

gcc --version   # 7.3.1 になっていること
g++ --version

JDK8 と JDK11 の配置(/opt/java)

/opt/java 作成

mkdir -p /opt/java
cd /opt/java

JDK8 をダウンロード&展開(例:Temurin 8u472)

wget https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u472-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u472b08.tar.gz
tar xvf OpenJDK8U-jdk_x64_linux_hotspot_8u472b08.tar.gz
# /opt/java/jdk8u472-b08/ ができる想定

JDK11 を「ヘッダ用」として配置

cd /opt/java
wget https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.23+9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz
tar xvf OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz
# /opt/java/jdk-11.0.23+9/ ができる想定

JDK8 の jvmti.h を JDK11 版に差し替え(ビルド用ハック)

# バックアップ
cp /opt/java/jdk8u472-b08/include/jvmti.h \
   /opt/java/jdk8u472-b08/include/jvmti.h.backup

# JDK11 の jvmti.h で上書き
cp /opt/java/jdk-11.0.23+9/include/jvmti.h \
   /opt/java/jdk8u472-b08/include/jvmti.h

JAVA_HOME と PATH を設定

export JAVA_HOME=/opt/java/jdk8u472-b08
export PATH=$JAVA_HOME/bin:$PATH
java -version

新しい perf_event.h を用意

カーネル付属の perf_event.h が古いので、別ディレクトリに新しいものを置く。

mkdir -p /root/ap-headers/linux
cd /root/ap-headers/linux

wget https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/perf_event.h \
     -O perf_event.h

ls -l perf_event.h   # 取得できていること

async-profiler 2.9 ソース取得

cd /root
git clone https://github.com/async-profiler/async-profiler.git
cd async-profiler
git checkout v2.9

ビルド

devtoolset-7 が有効なシェルで、JAVA_HOME も通っている前提。

cd /root/async-profiler

make clean
make EXTRA_CFLAGS="-I /root/ap-headers"

これで以下が生成される:

  • build/libasyncProfiler.so
  • build/jattach
  • build/async-profiler.jar
  • build/converter.jar など
ls build

VM 内で簡単な動作確認(任意)

cd /root
cat > Test.java << 'EOF'
public class Test {
    public static void main(String[] args) throws Exception {
        while (true) {
            busy1();
            busy2();
        }
    }
    static void busy1() {
        for (int i = 0; i < 200000; i++) {
            Math.log(i + 1);
        }
    }
    static void busy2() {
        for (int i = 0; i < 400000; i++) {
            Math.sin(i + 1);
        }
    }
}
EOF

javac Test.java
java Test &

pgrep java   # または jps で PID を確認
cd /root/async-profiler
./profiler.sh -e cpu -d 10 -f test.html <PID>

CentOS 6.5 本番へ持っていくファイル

最低限必要なのは次の3つ:

  • /root/async-profiler/build/libasyncProfiler.so
  • /root/async-profiler/build/jattach
  • /root/async-profiler/profiler.sh

CentOS 6.5 側では:

cd /opt/async-profiler
chmod +x profiler.sh build/jattach

# Java PID を確認してから
./profiler.sh -e cpu -d 20 -f cpu.html <PID>