5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

クロス開発環境でperf

Last updated at Posted at 2020-07-19

はじめに

組み込みの現場では、リソースの制約からデバッグシンボルがstripされた実行ファイルが実機にインストールされていることが多いです。
結果として、perf topを実行してもどの関数を実行中なのか基本的には解決できず、アドレスで表示されてしまいます。

perfコマンドはそのような環境のために、実機で保存したprofile情報を、PCでデバッグシンボルとともに解析するオフライン解析の仕組みが用意されています。

本記事では、QEMU環境を例にクロス環境でperfを使いオフライン解析をする流れを、備忘メモとして残しておきます。

今回使った環境は以下のとおりです。

  • buildroot : 2020.02.3
  • QEMU: 4.2.0
  • OS (host) : Ubuntu 18.04.4
  • linux kernel (host) : 5.3.0-62-generic
  • perf (host) : 5.3.18
  • linux kernel (target) : 4.19.91
  • perf (target) : 4.19.91

実験環境構築

buildrootを使って、aarch64のQEMU環境を用意します。
(いつからかQEMUもビルドしてくれるようになったので、構築がさらに楽になってます。ありがたや。)

wget https://buildroot.org/downloads/buildroot-2020.02.3.tar.bz2
tar xf buildroot-2020.02.3.tar.bz2 
cd buildroot-2020.02.3/

cat <<EOS >> configs/qemu_aarch64_virt_defconfig
BR2_ENABLE_DEBUG=y
BR2_PACKAGE_LINUX_TOOLS_PERF=y
EOS

cat <<EOS >> board/qemu/aarch64-virt/linux.config
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
EOS

make qemu_aarch64_virt_defconfig
make BR2_JLEVEL=$(nproc)
export PATH="$PWD/output/host/bin/:$PATH"

いくつか今回の実験用に、configを有効にしています。

  • Buildrootのconfig

    • BR2_ENABLE_DEBUG: 各パッケージのビルド時に、デバッグシンボルを有効にします。staging以下にデバッグシンボル付きのバイナリを保存します。
    • BR2_PACKAGE_LINUX_TOOLS_PERF: perfコマンドを追加します。
  • Linuxのconfig

    • CONFIG_DEBUG_INFO: vmlinuxをデバッグシンボル付きでビルドします。
    • CONFIG_DEBUG_KERNEL: kernelのデバッグ機能を有効にします。CONFIG_DEBUG_INFOを有効にするために必要です。

readme.txtのとおり、下記コマンドでビルドした仮想環境を立ち上げることができます。

qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -smp 1 -kernel output/images/Image -append "rootwait root=/dev/vda console=ttyAMA0" -netdev user,id=eth0 -device virtio-net-device,netdev=eth0 -drive file=output/images/rootfs.ext4,if=none,format=raw,id=hd0 -device virtio-blk-device,drive=hd0

perf record: プロファイル情報の取得

perf recordコマンドでプロファイル情報を取得できます。

取得するプロファイル情報はオプションによって色々と変更できますが、
ここでは-aオプションでシステム全体のプロファイルを取得します。
また、--call-graph fpオプションで、backtrace情報を併せて取得しています。
perfはbacktraceの算出方法をいくつかサポートしていますが、ここではframe pointerを使た方式を指定しています。

[On Target (QEMU)]
perf record -a --call-graph fp

計測が完了したらCtrl-Cで終了します。
するとカレントディレクトリにperf.dataが保存されているので、これを解析するためホストPCに転送します。
ネットワーク転送など方法は色々ありますが、今回はQEMUなのでディスクイメージをそのまま覗きます。

[On Host PC]
cd output/images
mkdir -p mnt
sudo mount -t ext4 rootfs.ext2 mnt
sudo cp mnt/root/perf.data perf.data
sudo umount mnt
cd ../../

なお、多少負荷がかかっていないと見ても面白くないので、とりあえず計測中にseqを回しました。

[On Target (QEMU)]
seq 100000 > /dev/null

perf report: 取得したプロファイル情報の解析

kernelのシンボルは-kオプションで、ユーザ空間のシンボルは--symfsで読み込むことができます。
確認した限り、kernelのシンボルとユーザ空間のシンボルを同時に読み込むことはできないようです。
少し手間ですが、都度切り替える必要がありそうです。

(2020/08/10追記) -kオプションに対して絶対パスでkernelイメージを指定することで、kernelのシンボルとユーザ空間のシンボルを同時に読み込むことができます。

[On Host PC]
perf report -i output/images/perf.data --symfs output/staging/ -k ${PWD}/output/build/linux-4.19.91/vmlinux 

Screenshot from 2020-08-10 19-26-09.png

seqとして起動されたbusyboxseq_mainから呼び出されたprintfで時間がかかっていることが読み取れます。
さらにaを押下すると、命令・行レベルでどこに時間がかかったかを表示することができます。(perf annotate相当)

[k]となっているのがkernel空間で、[.]となっているのがユーザ空間です。
例えばkernelで時間を使っているのは、swapperコンテキストのarch_cpu_idleであることが読み取れます。

なお、クロス環境でなければ-F srcline-F srcfileなどで、対応する行番号やファイル名も表示することができますが、
内部でaddr2lineが呼び分けられていないのか、今回の環境では表示できませんでした。
とはいえプロファイル情報全体に対してaddr2lineを実行するとかなり時間がかかり使い勝手が良くないので、
実際に行番号・ファイル名が必要になったときだけ別途addr2lineを呼び出す、というのはどちらにせよ現実的なやり方だと思います(言い訳)。

参考

Perf Wiki
Profiling your Applications using the Linux Perf Tools
Buildroot - Making Embedded Linux Easy

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?