2019年7月31日水曜日

[Codefresh] Parallel 実行してみた

Codefresh で並列実行が使えるようになっていたので試してみました。
Use parallel steps in your Codefresh pipelines - Codefresh
無料プランでももちろん並列実行できます。
試してみた結果
iutest で試してみた結果がこちら。
もともとしていた、「benchmark test」に加えて、gcc の複数バージョンの docker コンテナでテストを実行しています。


YAML はこちらです。
version: '1.0'
stages:
  - checkout
  - build
  - test

steps:
  main_clone:
    title: Cloning main repository...
    type: git-clone
    stage: checkout
    repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}'
    revision: '${{CF_REVISION}}'
  BuildingDockerImage:
    title: Building Docker Image
    stage: build
    type: build
    image_name: srz-zumix/iutest
    working_directory: ./
    tag: '${{CF_BRANCH_TAG_NORMALIZED}}'
    dockerfile: ./tools/docker/Dockerfile
  RunningUnitTests:
    type: parallel
    stage: test
    steps:
      BasicTest-gcc9: &basic_test
        title: Running Basic Tests - gcc9
        image: gcc:9
        environment:
          - OUTDIR=gcc9
        commands:
          - mkdir test/${OUTDIR} || true
          - make -C test clean
          - make -C test test
      BasicTest-gcc8:
        <<: *basic_test
        title: Running Basic Tests - gcc8
        image: gcc:8
        environment:
          - OUTDIR=gcc8
      BasicTest-gcc7:
        <<: *basic_test
        title: Running Basic Tests - gcc7
        image: gcc:7
        environment:
          - OUTDIR=gcc7
      BenchmarkTest:
        title: Running Benchmark Tests
        image: '${{BuildingDockerImage}}'
        working_directory: IMAGE_WORK_DIR
        entry_point:
          - /bin/sh
          - /codefresh/volume/cf-generated/unit_test_script
        create_file:
          path: /codefresh/volume/cf-generated
          name: unit_test_script
          content: |-
            cd /codefresh/volume/iutest
            cd test
            make -C benchmark
            make bench
    on_success:
      metadata:
        set:
          - '${{BuildingDockerImage.imageId}}':
              - CF_QUALITY: true
    on_fail:
      metadata:
        set:
          - '${{BuildingDockerImage.imageId}}':
              - CF_QUALITY: false

※執筆時現在は構成が異なってます。
※さらに使ってみてどうだったのかは別途書きたいと思ってます。

やり方
上記の YAML を例に説明していきます。
詳細は公式のヘルプを見てもらったほうが良いと思います。
といっても基本的には type を parallel にするだけなんですけどね。

下記のように、type: parallel にしたら steps: 以下に並列実行するステップを書くだけです。
RunningUnitTests:
    type: parallel
    stage: test
    steps:
      BasicTest-gcc9: &basic_test


ハマったこと・感想など
以下は、導入してみて躓いたところと感想を書いていきます。
git-clone したパスは共有
並列コンテナで同じ場所を使います。
なので、作業が競合するような場合は注意が必要です。

iutest でも、ビルド結果の出力先が同じだったため問題になりました。
各並列コンテナごとにワークスペースを用意するなどしたほうが良さそうです。

キャッシュ
キャッシュがあるので、クリーンビルドを想定しているとハマるかもしれません。
https://codefresh.io/codefresh-news/parallel-pipelines/
Codefresh runs a git reset and a git clean in your project repository everytime a pipeline starts. This means that all artifacts that you wish to be cached should be in your .gitignore file. A common example would be the node_modules folder. If you don’t place it in .gitignore, it will be deleted at the start of each build making it much slower.
git reset; git clean を行うので、.gitignore で無視指定されているものは残ったままになります。

iutest ではたまたまテストのビルド結果が .gitignore にかかれていたため、キャッシュされていました。
これのおかげで爆速でテストできてました。
ただ、今は clean ビルドするようにしてます。
(※現在はどの程度のテストが並列でできるか検証しているので、ゆくゆくはキャッシュ使っていきたい)


明示的にクリーンビルドをしてあげる、またはキャッシュを利用してビルド速度を上げるなど、使いみちに合わせた運用が必要です。

Join ができる

まだ使ってないんですが、Join ができるのはかなり嬉しい
wercker で join ができないのがつらくてな・・・


最後に
(なぜか)、フリートライアル中なので今のうちにいろいろ試してみたいと思います。
また、Free Plan になったときのことも考えて検証していく予定。
(すでに、SMALL RESOURCE キツイ・・・となってるので頑張る予定・・・)

2019年7月24日水曜日

[Wandbox] 処理速度比較したいときのテンプレ

C++ 書いてる(じゃないな見てる)と、これはこう書いたほうが速いんじゃないか、こう書いたほうが簡潔になるけどパフォーマンス落ちないかな、と思うことが多々あります。
そんなときは、サクッと Wandbox で試してみるのですが毎回計測コードをどう書くんだっけ?となっていたのでテンプレを用意しました。





2019年7月16日火曜日

[Visual Studio] ステップフィルターのカスタマイズでデバッグを楽にする

かなり前に Visualizer を紹介しましたが、今回はステップフィルターの紹介をします。
ブログズミ: [Visual Studio] デバッガー変数表示のカスタマイズ

Visual Studio ではステップインする際に、
特定の関数には入っていかないようにする設定がユーザー定義でできるようになっています。
Customize C++ stepping behavior independent of Just My Code settings

それを設定して何が便利なのか?
よくある事例で見てみましょう。

まずは設定なし。

そして、設定あり。


どちらも UnitTestSource::GetInstance().Initialize(); の Initialize にステップインしようとしている様子です。
いかがでしょう?
前者のように GetInstance にいちいちステップインしちゃうのが煩わしく感じてる人は多いのではないでしょうか?

ステップフィルターを設定した後者は GetInstance() の中に入っていかなかったですね。
このように、1行に複数の関数呼び出しがある場合に、興味がない関数へのステップインをしないようにするとデバッグがしやすくなると思います。

今回紹介する .natstepfilter を使って、この煩わしさから開放されましょう!


設定の仕方
.natstepfilter 拡張子のファイルを作成し、
「%VsInstallDirectory%\Common7\Packages\Debugger\Visualizers」もしくは「%USERPROFILE%\My Documents\\Visualizers」に保存するだけです。

ファイルのフォーマットは xml になっています。
この xml で関数の指定とその関数に対して、ステップインするか、しないかの設定を行います。
以下は GetInstance にステップインしないようにする .natstepfilter の例です。

<Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>

.natstepfilter は複数のファイルに分けて書くことができますので、stl.natstepfiler と iutest.natstepfilter のように namespace や用途に合わせて分けておくと便利だと思います。



iutest の例
さて、上記で iutest での GetInstance の事例を紹介しましたが、
iutest では、テスティングフレームワークの利用者はフレームワークの内部実装には興味がなく、テストコードにのみ興味があるはずという考えのもと、テストコードから内部実装にステップインしないようにした natstepfilter を提供しています。

<?xml version="1.0" encoding="utf-8"?>  
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">  
    <Function>
        <Name>iutest::TestEnv::environments</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestSource::Run</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionSuccess</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionFailure</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionResult.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionHelper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertPred.*Helper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::PrintToString.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::WithParamInterface.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::Test::RecordProperty.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestImpl::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::detail::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iuutil::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::matchers.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::internal::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>std::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
</StepFilter>

ユーザーが集中したいコードにのみ、ステップインするのでテストコードのデバッグがしやすくなったのではないか、と思ってます。

Resharper C++ をインストールしていると利用できない
https://pleiades.io/help/resharper/Reference_Options_Tools_Debugger_CPP.html
Resharper C++ にステップフィルターの機能があるため、すべてそちらの管理になります。
そのため、.natstepfilter の設定は引き継がれません。(継承かインポートできると嬉しいですが・・・)

Resharper 使っている方はご注意くださいmm


最後に
Visual Studio は "知っていれば" 便利な機能が結構あります。
ツールは使ってなんぼ。ただ使ってるだけじゃもったいないです。

これまでもいくつか機能を紹介してきましたが、今後も Visual Studio にはお世話になると思うので、また便利な機能を知ったら紹介したいと思います。

では。

2019年7月11日木曜日

[GitHub] Squash and merge したブランチを自動でまとめて消す



PR を普通にマージしたときは、merged なブランチを列挙して branch -d すればよかったのですが、
(こんな感じ: git branch --merged | grep -v \\* | grep / | xargs -I % git branch -d %)
「Squash and merge」すると、実際にブランチをマージしているわけではないので、branch --merged に列挙されず、上記方法でお掃除できずに困ってました。

結構、ローカルブランチが溜まってきたのでお掃除したいなーと思い、調べてみたらドンピシャな記事がありました。
GitHub で Squash merge されたブランチを削除する · ryym.log

詳しいことは、こちらの記事を読んでいただければと思います。


で、これで終わると、この記事自体の内容がないよう、となってしまうので、自分好みにカスタムした alias をおいておきます。

del-squashed-branch = "!f(){ base_branch=${1:-master} && echo ${base_branch} && git checkout -q ${base_branch} && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base origin/${base_branch} $branch) && [[ $(git cherry origin/${base_branch} $(git commit-tree $(git rev-parse $branch^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done; git checkout -q -;};f"
  del-sq = !git del-squashed-branch `git def-branch`
  def-branch = !git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-

もとの shell command だと master との比較になってましたが、他のブランチを指定できるようにしました。
iutest の開発中は develop に PR 出して、ある程度安定したら master にマージするようにしているので、
develop ブランチを指定して、お掃除したかったのでこうしました。

また、短いエイリアスの方はデフォルトブランチを指定するようにしました。
(これは仕事のときに使うことを想定してこうした)

今回は以上です。


追記
git symbolic-ref --short refs/remotes/origin/HEAD | cut -d "/" -f 2
では正しく GitHub のデフォルトブランチを取得できてませんでした。
git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-
に修正しました。


2019年7月5日金曜日

[Blogger][AdSense] 「ads.txt ファイルが含まれていないサイトがあります」 に対応した

このブログでは Google AdSense で広告掲載をしています。
たまーにレポートを眺めに AdSense を見に行くのですが、いつの間にか以下のような警告文が出るようになってました。
「要注意 - ads.txt ファイルが含まれていないサイトがあります。収益に重大な影響が出ないよう、この問題を今すぐ修正してください。」



収益にこだわりはないのですが、警告は無視できない体質なので対応しました。

ads.txt とは?
警告文のヘルプを開くと以下のようなことが書かれています。


Blogger に ads.txt を設定する
Blogger の場合のヘルプもちゃんとあります。


ヘルプに従えば問題なく設定できると思います。





ここに書く内容は、AdSense のヘルプを参考に以下のように入力します。

google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0

「pub-0000000000000000」の部分は、サイト運営者ID に置き換えてください。
サイト運営者 ID を確認する - AdSense ヘルプ

入力ができたら、「変更を保存」で設定完了です。
再び、AdSense にログインしてみたところ、警告が消えました!

よかったよかった。