2020年6月29日月曜日

Wandbox の CLI ツールを作ってみた


タイトルの通りコマンドラインツールを作ってみました。
リポジトリはこちら。https://github.com/srz-zumix/wandbox-api/

言語は Python で PyPI に Publish してますので、 pip install wandbox-api ですぐに使えます!
PyPI に初めて Publish しました〜
この辺は「Github ActionsでPyPIにパッケージを公開する」を参考に、GitHub Actions で tag をトリガーに Publish されるようにしました。
name: PyPI Publish
on:
  push:
    tags:
      - v*

jobs:
  pypi:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@master
    - name: Set up Python 3.7
      uses: actions/setup-python@v1
      with:
        python-version: 3.7
    - name: Init .pypirc
      env:
        PYPI_USERNAME: __token__
        PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
      run: |
        echo -e '[pypi]' >> ~/.pypirc
        echo -e "username = ${PYPI_USERNAME}" >> ~/.pypirc
        echo -e "password = ${PYPI_PASSWORD}" >> ~/.pypirc
    - name: Publish
      run: |
        pip install twine wheel
        python setup.py sdist bdist_wheel
        twine upload --repository pypi dist/*


現在の機能は、Wandbox が対応している言語・コンパイラー・オプションのリストアップとコンパイル&実行です。また、C++ 用に特化した wandbox-cxx コマンドもあります。
使用例
言語リストを取得
$ wandbox lang
Bash script
C
C#
C++
CMake
CPP
CoffeeScript
Crystal
D
Elixir
Erlang
F#
Go
Groovy
Haskell
Java
JavaScript
Lazy K
Lisp
Lua
Nim
OCaml
OpenSSL
PHP
Pascal
Perl
Pony
Python
R
Rill
Ruby
Rust
SQL
Scala
Swift
TypeScript
Vim script
コンパイラーのリストを取得
-l オプションで言語を選択してリストアップします。言語指定がない場合はすべての言語のコンパイラーをリストアップします。
$ wandbox -l C++ compiler
gcc-head
gcc-9.3.0
gcc-9.2.0
gcc-9.1.0
gcc-8.3.0
gcc-8.2.0
gcc-8.1.0
gcc-7.3.0
gcc-7.2.0
gcc-7.1.0
gcc-6.3.0
gcc-6.2.0
gcc-6.1.0
gcc-5.5.0
gcc-5.4.0
gcc-5.3.0
gcc-5.2.0
gcc-5.1.0
gcc-4.9.3
gcc-4.9.2
gcc-4.9.1
gcc-4.9.0
gcc-4.8.5
gcc-4.8.4
gcc-4.8.3
gcc-4.8.2
gcc-4.8.1
gcc-4.7.4
gcc-4.7.3
gcc-4.6.4
gcc-4.5.4
gcc-4.4.7
clang-head
clang-10.0.0
clang-9.0.0
clang-8.0.0
clang-7.0.0
clang-6.0.1
clang-6.0.0
clang-5.0.0
clang-4.0.1
clang-4.0.0
clang-3.9.1
clang-3.8.1
clang-3.7.1
clang-3.6.0
clang-3.5.0
clang-3.4
clang-3.3
clang-3.2
clang-3.1
zapcc-2017.08
zapcc-1.0.1
コンパイラーのオプションを取得
-c オプションでコンパイラーを選択すると、そのコンパイラーで使用できるオプションをリストアップします。指定がない場合はすべてのオプションをリストアップします。

$ wandbox -c clang-head option
C++: 
warning (default)
optimize
cpp-verbose
boost-1.73.0-clang-head (default)
  boost-nothing-clang-head
  boost-1.60.0-clang-head
  boost-1.61.0-clang-head
  boost-1.62.0-clang-head
  boost-1.63.0-clang-head
  boost-1.64.0-clang-head
  boost-1.65.0-clang-head
  boost-1.65.1-clang-head
  boost-1.66.0-clang-head
  boost-1.67.0-clang-head
  boost-1.68.0-clang-head
  boost-1.69.0-clang-head
  boost-1.70.0-clang-head
  boost-1.71.0-clang-head
  boost-1.72.0-clang-head
  boost-1.73.0-clang-head
sprout
msgpack
gnu++2a (default)
  std-c++-default
  c++98
  gnu++98
  c++11
  gnu++11
  c++14
  gnu++14
  c++17
  gnu++17
  c++2a
  gnu++2a
cpp-no-pedantic (default)
  cpp-no-pedantic
  cpp-pedantic
  cpp-pedantic-errors
C++ のコードをビルド・実行する
wandbox-api パッケージには C++ 用のコマンドとして、wandbox-cxx と wandbox-g++/wandbox-clang++ が含まれています。
cxx は wandbox コマンドに -l C++ を指定したのと同等です。wandbox-g++/wandbox-clang++ はさらに -c オプションでコンパイラーの指定をしたものになります
(バージョンはそれぞれ head)
また、これらは通常の wandbox コマンドのコマンドラインオプションに加えて、 C++ コンパイラー向けの Wandbox オプションがコマンドラインオプションで設定できるようになっています。
  --std VERSION         set --std options
  --boost VERSION       set boost options version X.XX or nothing
  --optimize            use optimization
  --cpp-verbose         use cpp-verbose
  --sprout              use sprout
  --msgpack             use msgpack
run に続く引数は、コンパイラーへの引数としてそのまま渡されます。
$ wandbox-clang++ run main.cpp test.cpp
program_message:
Hello, Wandbox!
test
$ wandbox-clang++ run main.cpp test.cpp -DTEST
program_message:
test
test
-s オプションを付けると permlink を発行できます。
wandbox-clang++ -s run main.cpp test.cpp -DTEST
program_message:
test
test


permlink: TuvMXWckFrkxGPAs
url: https://wandbox.org/permlink/TuvMXWckFrkxGPAs
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/6AGrKCojBOo1oCUv


使用したソースコードはこちらです。
今後
今後、ちまちまと他の言語のコマンドも追加していこうと思います。
もちろん PR 大歓迎です!
今回は以上です。では。



2020年6月23日火曜日

[AppVeyor] Python3 系を使うようにする

AppVeyor で現在提供されているエージェント(環境)は Python 2.7 がデフォルトになっているので、Python 3 系に変更しました。
AppVeyor の環境にプリインストールされている Python は下記から確認できます。

あとはお好きなバージョンのディレクトリを PATH に追加したら終わりです。

version: 1.0.{build}
branches:
  only:
  - master
image: Visual Studio 2019
init:
- cmd: SET PATH=C:\Python38;C:\Python38\Scripts;%PATH%
以上です。

2020年6月18日木曜日

[GIT] 「ファイルのタイムスタンプをコミット日時に合わせる」を爆速にした

svn には use-commit-times がある。
git だとないが git ls-files と git log の組み合わせで対応できる。
そしてそのスクリプトも git-set-file-times としてある。
ここまでは既出な情報である。


私も過去の記事を見て知った口だ。

さて、ここで今この記事を読んでいる読者は、私と同じように何らかの理由があってタイムスタンプを変更したい方が多いのではないか、と思います。
私がタイムスタンプを変更したい理由は、とあるビルドシステムがファイルのタイムスタンプを使って差分ビルドの「ビルドする・しないを決める」、かつ、同じワークスペースでブランチを行き来するため pull したときのタイムスタンプが、そのブランチにおけるファイルの変更と一致しないため、差分ビルドしたときに入ってほしいものが入ってない、入ってほしくなものが入ってしまった。という事象の解決のためでした。

なんか、パイプラインの問題でもある気がするけど、
git の変更履歴とファイルのタイムスタンプが時系列的にあえば、ビルドシステム的に解決。
しかもその方法はすでにあってコマンド1つで実現するのであれば、利用しちゃいますよね。
で、試したところ・・・

時間がかかりすぎてハンパない!!

個人開発のリポジトリで試したときは処理時間が気にはならなかったのですが、
実際それがほしいリポジトリは、超巨大・非テキスト・長履歴で、全部のファイルのタイムスタンプを設定するのに 15 分強 (1,000s くらい)かかってました。。

結論

紆余曲折があるのだが、先に結論だけ書く。
冒頭の Qiita で紹介されていた git-set-file-times に 1 つだけオプションを追加することで、10 倍速、約1分半(100s くらい)で処理できるようになりました!
修正した git-set-file-times はこちら。

追加したオプションは -c diff.renames=false です。
ファイルが更新されたことさえ知れればよく、Add なのか Move なのかは重要ではないので、 false にしても問題ありません。
git の diff は diff.renameLimit の一致度?(デフォルト 50%)で rename 判断をしてるみたいなので、おそらくファイルごとに一致度を調べてたから遅かったと思われます。

あと、↑の git-set-file-times では見つからなかったファイルに対して、git log の最後のコミットのタイムスタンプで更新するようも修正してます。

これは git-set-file-times --since 2020/06/17 のように log コマンドのオプションを設定できるためです。(この場合 2020/6/17 以降の変更はコミットのタイムスタンプ、2020/06/17 以降に変更がなかったファイルは全部同じタイムスタンプが設定されます。)

紆余曲折
コミットを辿るんじゃなくファイルリストごとに git log すればいいだけでは?
まずはじめに考えたのは、git ls-files で取得したファイルリストから、分散してファイル1つ1つ最終コミットを取得してタイムスタンプを更新するものでした。

クソ遅い!

git の仕組みを少し理解したので今ならわかりますが、この方法はクソ遅いです。
なんとなくファイル単位で git log したときのオーダーは O(1) なイメージで、すぐ取ってこれると思っていたのですが、そんなことはなく、実は commit を辿って辿って目当てのファイルでフィルタリングしてるだけみたいです。

なので、git-set-file-times のやり方で問題ないです。
(ファイルリストが空になるまで log を辿る。)

git コマンドじゃなくて git そのものを扱えばいいじゃない
git log からコミットのタイムスタンプとファイルリストを取得しているが、git そのものを扱えば速いんじゃない?と思い↓を作成しました。

libgit2/git2go を使って Go でコマンドを作成してます。

で、これも遅かった。
どれくらい遅かったかというと、git-set-file-times の 10倍遅かった

Go 書くの初めてだったので、お前のコードが悪い or libgit2/git2go の使い方が悪いのかもしれない。
ただ、Go 側で diff のファイルを foreach するよりも、ToBuf で文字列化したものを受け取って Split したほうが若干速かったので、C の呼び出しは減らしたほうがいいのかな?と思っている。

悔しいので Go で git log コマンドコールしてパースするバージョンも書いてみたけど、速度は対して変わらず。
まぁ git-set-file-times でいいわ、--since とかできるし。って結論になった。

また時間があれば C++ で再実装したり、別の言語のバインディングを使ってみたいと思う。

完璧ではないがリミットを設けたらどうだろうか?
first commit 以来、一切変更されてないファイルがあるとログを全部辿ることになるのでそりゃ時間かかるよな。そんな極端でなくてもあまり更新されないファイルって存在すると思うので、結構な数のログを辿らないと終わらないケースは多々ありそう。

と、思いながら git-set-file-times 眺めてたら、git log コマンドで引数を受け付けてたので、ログ数制限できるなーと思ったのでやってみた。

git-set-file-times --since 2020/06/01

って感じ。

これは、思ったとおりすぐ終わった!

じゃ、あとは残ったファイルには一律同じタイムスタンプつけとけば ok だなってことで、現在の git-set-file-times のようになりました。

まぁ完璧ではないけど、求められているものにはなったんじゃない??
いやーめでたしめでたし。

だったんですが、ふと気づいたのです。
なんか警告出てるな、と。

diff.renameLimit の警告が我を救った
warning: only found copies from modified paths due to too many files.
warning: you may want to set your diff.renamelimit variable to at least XXXX and retry the command
たまたまこんな警告が出てたんで、警告はでないようにしたいなと思ったのがきっかけ。
まず、diff.renameLimit=0 にしてみたんですが、おそろしく処理時間がかかるようになりました。 15分どころか、数時間待っても終わらず kill しました。。

ここでようやく気づきます。
Rename かどうかは重要ではない

ここからゴールはもうすぐです。
rename かどうかの追跡は git config の diff.renames で設定できることを調べて知ります。
config を一時的に変えてコマンド実行したいなと思い調べると、サブコマンドの前のオプションで -c 使えばいいことがわかります。

つまり git -c diff.rename=false log こうです。
そして、完成!!

試しに実行したときにすぐに完了したので感動しましたね。

最後に

git 奥深い。。。

2020年6月15日月曜日

[Visual Studio] .natvis/.natstepfilter をプロジェクトに追加してウォッチ・ステップインしやすくする

つい先日同僚からの情報で初めて知ったのですが、.natvis はプロジェクトに追加することでプロジェクト固有の Visualizer を設定できるようです。

.natvis って?という方は、過去に記事を書いているのでそちらを参照してください。

今まで Visual Studio 共有な形でインストールしていたので、プロジェクトごとに調整できるのは嬉しいですね!
また、.natvis は .pdb にも埋め込まれるようなので、起動した実行ファイルにアタッチしてデバッグ開始した場合でも、.pdb から .natvis を読み込んで適用されるようです。
(.pdb への埋め込みは設定で解除できます。詳細は最初のリンクへ)

iutest.natvis の例
.natvis がどのようなものか簡単に iutest が用意している .natvis で見てみたいと思います。(iutest は自作の C++ テスティングフレームワークです)

.natvis ファイルは以下。
  
<?xml version="1.0" encoding="utf-8"?>
<autovisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
  <type name="iutest::Test">
    <displaystring>{{ name={test_info_-&gt;m_testname}}}</displaystring>
    <expand>
      <item name="TestName">test_info_-&gt;m_testname</item>
      <item name="TestCaseName">test_info_-&gt;m_testcase-&gt;m_test_case-&gt;m_testcase_name</item>
      <item name="Results">test_info_-&gt;m_test_result</item>
    </expand>
  </type>
</autovisualizer>

これを読み込んでテストでブレークすると以下のように表示されます。


未加工ビューを開くと .natvis 適用していない素の状態を確認できます。


このように iutest では、this から不要なものを取り除いて見やすくした値が確認できるようにしています。

CMake に .natvis を追加する
普通に .natvis を追加すれば ok 。
iutest では、MSVC の場合には add_executable に .natvis を追加しています。

function(iutest_add_executable name)
if (MSVC)
  add_executable(${name} ${ARGN} ${IUTEST_ROOT_DIR}/tools/VisualStudio/Visualizers/iutest.natvis)
else()
  add_executable(${name} ${ARGN})
endif()
endfunction()
.natstepfilter はどうなのか?
Visual Studio の Visualizer にはステップフィルターもあります。
(Visualizer なのかな?って気がしてるが Visualizers ディレクトリに配置するのでそう呼んでる)
ステップフィルターについてはこちらも参考にしてください。

結論から書くと「まだできません」。要望が上がってはいます。

↑のブログでも書きましたが、GetInstance とかプロジェクト固有でステップインしたくないものって結構あると思うんですよね。
.natvis はグローバルにインストールされていても無害なことが多いと思いますが、ステップフィルターは条件をしっかり書かないと、他のプロジェクトのデバッグを阻害することになりかねないですからね。。
今後対応されることを期待します

それでももう少し楽にできないか
現時点では、公式ドキュメントにかかれているとおりに、Visualizers フォルダにコピーして使うことになります。

チームメンバーに .natstepfilter を 「%USERPROFILE%\My Documents\<Visual Studio のバージョン>\Visualizers」 フォルダーにコピーして使ってというのも手間なんで、カスタムビルドルールで勝手にインストールされるようにしてみました。

.natstepfilter ファイルをプロジェクトに追加したら、ファイルのプロパティを開いて、項目を「カスタムビルドツール」にしビルドから除外を「いいえ」にします。
カスタムビルドツールの設定は、コマンドラインに「xcopy /I /Y "%(FullPath)" "$(VisualStudioDir)\Visualizers\"」を設定、出力ファイルを「$(VisualStudioDir)\Visualizers\%(Filename)%(Extension)」に設定します。

この状態でビルドをすると、.natstepfilter ファイルが Visualizers フォルダにコピーされ、デバッグ実行時にはコピーされた .natstepfilter がロードされます。
おまけ

std::string を s8 (UTF-8)表示する .natvis






2020年6月9日火曜日

[CI] Razorops 始めました

iutest の新しい CI サービスとして Razorops を使い始めました。
Razorops とは
Razorops は Container-Native な CI/CD サービスです。
他の Container-Native な CI サービスだと、Drone や Codeship Pro 、Codefresh とかがあげられます。

気になる Pricing は
本ブログで紹介するということは、FREE プランがあります。
ビルド回数無制限なのはありがたいですね。
Docker Layer Caching や Kubernetes GitOps は Basic プランでは使えない、また ENTERPRISE プランだと 20 並行可能となっていますが、Basic プランでは特に記載ないので 1 でしょうか。こちらは実際に使ってみて確認していきたいと思います。

では、さっそく SignUp します。

Sign-Up
GitHub アカウントでのサインナップとかはできないので、まずはメールアドレス等を必要事項を入力します。

「Sign up」ボタンを押すと完了です。
ダッシュボードが開くので、プロジェクトの作成をしていきましょう。



プロジェクト作成
「Create」ボタンを押すとリポジトリの選択が開きます。
今回は GitHub を選択します。まだ GitHub との接続ができてないので、接続を許可しましょう。




Integrations に戻ってくるので、続いて App のインストールをします。
Connect ボタンからインストールをすると接続設定が完了となります。



接続ができたら、Pipelines にもう一度移動しリポジトリの選択をします。


リポジトリの解析が始まるので少し待ちます。

.razorops.yml ファイルが必要になりますが、まだ用意してないのでここでは「Skip」をします。

これで新しいパイプラインが作成できました。
次に YAML を作成しビルドを走らせてみます。

YAML の作成
ドキュメントを参考に YAML ファイルを作成します。
今回 iutest で実施したいのは、既存の Docker コンテナ上でのビルドとテストなので Freesytle のタスクを記述します。


  tasks:
  centos-tests:
    image: srzzumix/gcc3:centos5
    commands:
      - find . -type f \( -name \*.hpp -or -name \*.cpp -or -name \*.ipp \) -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;
      - make -C test -j4
      - make -C test test
特に難しい部分はありません。
実行したい image の指定をしてコマンドを列挙するだけです。

実行結果
実行すると以下のようになります。

バッジ
残念ですが、バッジはまだ対応していないようです。
対応予定はあるようとのことでしたので、待ちましょう。
最後に
まだまだ知らない CI サービスがあるもんですね。
Razorops は躓くことなく、すんなり始めることができました。
まだまだ使い始めたところなので、今のところ、特筆するような特徴は見つかってませんが、普通に使える CI サービスだと思いました。
(普通って大事ですよね。)

またアップデートがあったらブログにしたためたいと思います。
では。


2020年6月2日火曜日

Windows Performance Analayzer で C++ ビルド時間のプロファイルをしてみよう!


最近 clang の -ftime-trace オプションと chrome://tracing を使ってビルド時間の可視化をしてみましたが、Microsoft が提供している WPA(Windows Performance Analyzer | Microsoft Docs)も便利そうということで試してみました。


使い方
セットアップ
使い方は↑のツイートのリンク先ブログにも記載されています。

必要なのは VS2019 と Windows ADK です。
リンク先からダウンロードしてインストールしてください。
VS2019 では Community Edition でも問題なくプロファイリングできます。

次に VS2019 のインストールディレクトリから perf_msvcbuildinsights.dll を ADK のインストールディレクトリにコピーします。

「C:\Program Files (x86)\Microsoft Visual Studio\2019\{Edition}\VC\Tools\MSVC\{Version}\bin\Hostx64\x64」
→「C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit」

(Visual Studio の方のパスは環境によって変わるので適宜変更してください。筆者環境では「C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\Hostx64\x64」でした)
筆者が試したときは、ADK インストールディレクトリにすでに同名ファイルがありましたので、バックアップを取ってコピーしました。


このコピーをしておかないと C++ Build Insights (Template instantiations や Files)が見られないので注意してください。

トレース
準備が整ったらプロファイルを取得してみましょう。
こちらもブログの手順のとおりに行えば ok です。

まずは、「x64 Native Tools Command Prompt for VS 2019」を管理者権限で起動します。(vcvarsall.bat などから環境セットアップしたプロセスでも ok)


vcperf /start /level3 name

でトレースを開始します。
開始できたら、普通に Visual Studio でビルドしてください。(IDE からでもコマンドからでもどちらでも ok)

ビルドが終わったら vcperf を停止させます。このとき出力ファイルを指定します。

vcperf /stop /templates name output.etl


WPA で表示する
etl ファイルができたら WPA で表示してみましょう。
etl ファイルをダブルクリックすれば WPA が起動します。
ローディングが終わると以下のように表示されます。


あとは、Diagnostics から項目を選んでいけばビルドで何にどれだけ時間がかかっているのかが確認できます。



CircleCI で vcperf
ローカル環境でプロファイルを取得することもできますが、面倒なので CI でやるようにしてみました。今回使用した CI サービスは CircleCI です。
ターゲットとなるのはおなじみ「自作 C++ テスティングフレームワーク」の iutest です。

CircleCI を選択した理由は、すでに -ftime-trace の結果を CircleCI の成果物として保存するようにしていたので、vcperf の成果物も CircleCI に置こうと思ったからです。
それ以外の理由は特にありません。VS2019 がインストールされている Windows エージェントが使用可能なサービスであれば他でも問題ないと思います。(AppVeyor, Azure Pipelines, GitHub Actions, ...)
(※ CI-Spec で調査)

config.yml と計測用に追加したバッチファイルがこちら。
orbs:
  win: circleci/windows@2.2.0

jobs:
  vcperf:
    executor: win/default
    environment:
      CMAKE_GENERATOR_NAME: "Visual Studio 16 2019"
      CMAKE: "C:/CMake/bin/cmake.exe"
    steps:
      - checkout
      - run:
          name: install
          command: |
            $ProgressPreference = "SilentlyContinue"
            Invoke-WebRequest -URI https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-win64-x64.zip -OutFile $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip
            Expand-Archive $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip -DestinationPath "C:\"
            Rename-Item "C:\cmake-3.16.4-win64-x64" -NewName CMake
      - run:
          name: cmake
          shell: bash.exe
          command: |
            mkdir build && cd build && ${CMAKE} ../projects/cmake -G "${CMAKE_GENERATOR_NAME}" -A x64
      - run:
          name: vcperf
          shell: cmd.exe
          command: .circleci\vcperf_build.bat
      - store_artifacts:
          path: .\iutest.etl    
    call tools\VisualStudio\vcperf.bat /start /level3 iutest
%CMAKE% --build .\build
call tools\VisualStudio\vcperf.bat /stop /templates iutest iutest.etl

計測用にバッチファイルを別途用意しているのは config.yml の command で1つずつ処理しようとしたら vcvarsall.bat の exit 0 で処理が止まってしまったからです。
vcvarsall は vcperf.bat から呼び出されるようになってます。
もっと良い解決方法あれば教えて下さいmm

このジョブが完了すると Artifacts に iutest.etl がアップロードされています。
ダウンロードして WPA で確認してみましょう。

iutest のプロファイルを見てみる
では CircleCI で取得した etl ファイルを見てみましょう。

Build Explorer
まずは「Build Explorer」の結果↑
どのような処理がどのくらい時間がかかったかがわかります。
1ファイルのコンパイルにおいてどのようなことをしているのかも詳細に確認することができます。

Files
次に「Files」です↑
こちらは各ファイルの処理にどれだけ時間がかかったかがわかります。
また呼び出された回数もわかるので、Count が多いファイルは無駄に include されていないか確認すると良いかもしれません。

↑のようにファイルを展開すると、どこから include されたかどうかが1つずつ確認することができます。

Template Instantiations
最後に「Template Instantiations」です↑
こちらでは template の実体化にかかった時間がわかります。

デフォルトでは「Primary Template Name」が Visible になっているので、 すべての引数パターンが template クラス・関数名でまとめて表示されています。
こちらの Visible のチェックを外すと template 引数違いで時間順に並べられます。
これでボトルネックになっている template の実体化が見つけやすくなると思います。

また検索機能を使うことで、↓のように特定の名前に絞って表示することもできます。

Specialization Names のノードを開くと、どこから実体化されたかもわかるようになってます。

改善ポイント
さて、iutest に絞り込んだ場合 iuCsvFileParamsGenerator<float> の実体化がトップでした。
しかしながら、この iuCsvFileParamsGenerator は CSV ファイルからテストパラメータを読み込ませるときにしか実体化されない想定でした。
上記の2枚目の画像を見ていただくと、Count が 155 回記録されています。
今回記録したときのビルドでは複数のテストをビルドしていますので、おそらくテストの数(exe の数)だけ実体化されていそうです。

使うときにだけ実体化されるのが理想なので、詳細を追ってみたところ、iuCsvFileParamsGenerator<float>::ToParam の特殊化がありました。

おそらく、これが原因でしょう。
今回の記事はここまでですが、この修正結果については Twitter かブログで報告したいと思います。

最後に
WPA はプラットフォームは限られますが、clang -ftime-trace + chrome://tracing でプロファイルするよりも、ビルド時間のボトルネックになりやすい Template Instantiation を調べやすくていい感じだなと思いました。
セットアップや使い方も簡単なのでぜひやってみてください。

では。

追記(2020/06/15)

iuCsvFileParamsGenerator の特殊化をなくして、もっと低レベルでの特殊化(クラス外に追い出した)ところワーストから消えてることを確認しました。

今回の計測前後の etl ファイルをこちらに置いておいたので興味がある方は分析してみてください。