2
1

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 1 year has passed since last update.

cargo-flamegraph を Docker を利用して Mac 上で使う

Posted at

以前にcargo-profiler を Dockerを使ってMac上で実行する記事を書いたのですが、数ヶ月前に試したら上手く動かせなくなっていました1
メンテナンス状況もたまに自動ライブラリバージョンアップが入るだけ、になっているようだったので乗り換えを考えていたところ、cargo-flamegraph というプロファイラツールを見かけたのでこれを採用しました。

cargo-flamegraph も cargo-profiler 同様、Mac では動かなそうだったので、実行する上で Docker を使用しました。その手順をまとめています。

手順

Dockerイメージのビルド

$ docker build -t flamegraph .

コマンドを、下記の Dockerfile を設置したディレクトリで実行する。

Dockerfile
FROM debian:buster-slim

ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=1.68.2

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        ca-certificates \
        gcc \
        libc6-dev \
        wget \
        ; \
    dpkgArch="$(dpkg --print-architecture)"; \
    case "${dpkgArch##*-}" in \
        amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='bb31eaf643926b2ee9f4d8d6fc0e2835e03c0a60f34d324048aa194f0b29a71c' ;; \
        armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='6626b90205d7fe7058754c8e993b7efd91dedc6833a11a225b296b7c2941194f' ;; \
        arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='4ccaa7de6b8be1569f6b764acc28e84f5eca342f5162cd5c810891bff7ed7f74' ;; \
        i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='34392b53a25c56435b411d3e575b63aab962034dd1409ba405e708610c829607' ;; \
        *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
    esac; \
    url="https://static.rust-lang.org/rustup/archive/1.25.2/${rustArch}/rustup-init"; \
    wget "$url"; \
    echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
    chmod +x rustup-init; \
    ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
    rm rustup-init; \
    chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
    rustup --version; \
    cargo --version; \
    rustc --version; \
    apt-get remove -y --auto-remove \
        wget \
        ; \
    rm -rf /var/lib/apt/lists/*;

RUN apt update \
    && apt install -y linux-perf

RUN cargo install flamegraph \
    && chmod -R a+w $CARGO_HOME

(このファイルは、https://github.com/rust-lang/docker-rust/tree/61db4471f1ef23dacd217f4a67841cc09aa05858/1.68.2 の末尾に

RUN apt update \
    && apt install -y linux-perf

RUN cargo install flamegraph \
    && chmod -R a+w $CARGO_HOME

を書き加えたものになります。)

perf_event_open が実行できない問題の解消

この時点で flamegraph を実行しても、

perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error 1 (Operation not permitted)
perf_event_open(..., 0) failed unexpectedly with error 1 (Operation not permitted)
Error:
No permission to enable cycles:u event.

のようなエラーが出て、異常終了してしまいます。
こちらの記事によると、root 権限を持っていないために起きているらしいです。

今回は、同記事内に記載されている選択肢1の「'seccomp'を少しカスタマイズする」対処方法を取りました。手順は下記になります。

  1. seccomp のデフォルト設定ファイルをダウンロード。my_seccomp.json という名前で保存。
  2. my_seccomp.jsonsyscalls フィールドの配列に perf_event_open を書き加える。
  3. $ docker run 実行時に -security-opt seccomp=./my_seccomp.json のコマンドを付けて、seccomp ファイルとして設定する。

※セキュリティリスクを増す可能性がありそうです。実施は自己責任でお願いします。

プロファイル実行

下記を実行すると、cargo run --release を実行した場合のプロファイル結果が得られます。

$ docker run --rm --user "$(id -u)":"$(id -g)" \
    --security-opt seccomp=./my_seccomp.json \
    -v /your/cargo/project/path:/workspace \
    -w /workspace \
    flamegraph \
    cargo flamegraph

/your/cargo/project/path には、プロファイル対象のcargoプロジェクトのルートディレクトリを記載してください。)

ただ、自分の主な用途2では標準入出力のリダイレクトがしたくなるので、下記のようにコマンドを自由に表記できるオプションで使用しています。

$ docker run --rm --user "$(id -u)":"$(id -g)" \
    --security-opt seccomp=./my_seccomp.json \
    -v /your/cargo/project/path:/workspace \
    -w /workspace \
    flamegraph \
    bash -c "cargo flamegraph -- cargo run --release --bin a < in/0000.txt > out/0000.txt"

(in/0000.txtout/0000.txt が、入出力ファイルに当たります。)

実行すると、flamegraph.svg と perf.data というファイルが吐かれます。
flamegraph.svg が結果を図示した画像で、以下のようなものになります(perf.data の方はシステムデータ的なもののようなので気にしなくて良さそうです)。

image.png

関数ごとの実行時間がグラフの長さで表現されています。見やすくて良いですね。

  1. うろ覚えですが、出力表示が空、みたいな症状だった記憶です。

  2. 競技プログラミングのマラソンマッチという分野で主に使っています。この手のコンテストでは、入力を標準入力から受け取る形式が多いです。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?