新しいmacOS M1マシーンでどのくらいビルド時間が速くなるか調べてみた！

# はじめに
皆さんこんにちは！
CircleCIカスタマーサクセスマネージャーの小島です。
CircleCIカスタマーサクセスチームでは、お客様がCircleCIを最大限、効率良く、お客様の目標に合わせて活用していただけるよう、日々お手伝いをしております。
最近は暑くて暑くて、趣味のスキューバダイビングをするたびに早く人間を辞めて、魚になりたいと思っています。

3月にCircleCIがリリースした、macOSのM1マシーンはもう試されましたか？
CircleCIはビルド時間が速くなると言っているけど、消費クレジットが増えるし、、、
と心配されている方も多いようです。
本日は実際に速度の比較を行って、どのくらい速くなるか試してみたいと思います！


# 目次
- 利用プロジェクトについて
- Configファイルの設定
- ワークフローの実行結果
- macOSマシーンについてのお知らせ
- おわりに

 

# 利用プロジェクトについて
今回、CircleCIのソリューションエンジニアのTadashiさんのブログ[Tadashiさんのブログ](https://tadashi0713.dev/blog/circleci-m1-comparison-ja)を参考にさせていただきました！
Tadashiさんが比較された際は、M1 Largeのみしかリリースされていませんでしたが、
今回はM1 Mediumのリソースクラスも含めて比較させていただきました。

プロジェクトは以下を使用しました。Duckduck GoというCircleCIで利用しているエンジニアも数名しかいないというマイナーな検索アプリです。
[GitHub - duckduckgo/iOS: DuckDuckGo iOS Application](https://github.com/duckduckgo/iOS)


# Configファイルの設定
まず初めにCircleCI Orbを利用し、```executors```内に使用するマシーンとXcodeのバージョンを記述していきます。

unit_test(ユニットテストの実行)とintegration_test(インテグレーションテスト/UI テストの実行)ジョブの記述を行って、最後のワークフロー内でジョブを実行するマシーンを```executor```で指定しています。

今回指定したmacOS Gen2とM1リソースクラスのスペックは以下となります。

| Resource Class | CPU | RAM | Credits per min |
|:------------:|:------------:|:------------:|:------------:|
| macos.gen2.medium      | 4GB       | 8GB         | 75         |
| macos.m1.medium.gen1      | 4GB        | 6GB         | 150         |
| macos.m1.large.gen1      | 8GB        | 12GB         | 200         |



```YAML:config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@2.0.1
  macos: circleci/macos@2.3.4

executors:
  gen2_medium:
    macos:
      xcode: 14.3.1
    resource_class: macos.x86.medium.gen2
  m1_medium:
    macos:
      xcode: 14.3.1
    resource_class: macos.m1.medium.gen1
  m1_large:
    macos:
      xcode: 14.3.1
    resource_class: macos.m1.large.gen1

jobs:
  unit_test:
    parameters:
      executor:
        type: executor
    executor: << parameters.executor >>
    steps:
      - macos/preboot-simulator:
          device: iPhone 14
          version: '16.4'
      - checkout
      - run: git submodule update --init --recursive
      - ruby/install-deps
      - run: bundle exec fastlane unit_tests
      - store_test_results:
          path: fastlane/report.xml

  integration_test:
    parameters:
      executor:
        type: executor
    executor: << parameters.executor >>
    steps:
      - macos/preboot-simulator:
          device: iPhone 14
          version: '16.4'
      - checkout
      - run: git submodule update --init --recursive
      - ruby/install-deps
      - run: bundle exec fastlane integration_tests
      - run: bundle exec fastlane atb_uitests
      - store_test_results:
          path: fastlane/report.xml

workflows:
  gen2_medium_workflow:
    jobs:
      - unit_test:
          executor: gen2_medium
      - integration_test:
          executor: gen2_medium
  m1_medium_workflow:
    jobs:
      - unit_test:
          executor: m1_medium
      - integration_test:
          executor: m1_medium
  m1_large_workflow:
    jobs:
      - unit_test:
          executor: m1_large
      - integration_test:
          executor: m1_large
```

実際にこのconfigファイルを使用して実行した際に、CircleCI上ですぐにfailとなり、bundleのバージョンエラーに出くわしました。
![スクリーンショット 2023-07-28 14.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/9094d4b4-6dfa-8ea4-6fd9-632da7175c45.png)
bundleのバージョンを3.0.5をインストールしてもこのエラーがなかなかなくならず、3.0.6をインストールされると解消されました！

そして、[ドキュメント上](https://circleci.com/docs/using-macos/#available-resource-classes)ではXcodeの14.2までしかサポートしていないと書いてありますが、、、
![スクリーンショット 2023-07-28 14.37.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/252634cb-7cc9-b580-669d-69c18208f9e8.png)
最新の14.3.1を指定して問題なく実行できました！　むしろ、最新版を指定しないとXcodeのバージョンをアップデートするようなエラーも出ます。



# ワークフローの実行結果
さて、実際のワークフローの実行時間はどうなったでしょう？
![スクリーンショット 2023-07-27 16.44.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/8487360c-a88b-a4e6-6ed0-6fe198e11848.png)
m1_large_workflow - <b>4m 40s</b>
m1_medium_workflow - <b>5m 17s</b> (Testが１つfailしただけなので気にせず実行は完了)
gen2_medium_workflow - <b>9m 14s</b>

<b>Gen2 Mediumで9分</b>、<b>M1 Mediumを使用すると5分台</b>まで短縮することができました！！

Gen2 Medium使用時のCPUとRAMの占有率
![スクリーンショット 2023-07-27 16.44.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/da8dd2ff-0ab2-0c20-dfc5-e89797a5f4f0.png)
M1 Medium使用時のCPUとRAMの占有率
![スクリーンショット 2023-07-27 16.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/a8ac3666-caa0-ac1d-babd-3d74ca1df52f.png)
M1 Large使用時のCPUとRAMの占有率
![スクリーンショット 2023-07-27 16.45.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/c4241b31-484d-f44e-0cdf-42e73c78097d.png)



<b>クレジット消費量</b>
全てのワークフローにunit_testとintegration_testの２つのジョブが含まれています。
Gen2 Medium - gen2_medium_workflow - <b>1373 クレジット</b>
M1 Medium - m1_medium_workflow - <b>1552 クレジット</b>
M1 Large - m1_large_workflow　- <b>2247 クレジット</b>

クレジット消費量で見ると、圧倒的にM1 Largeの消費量は大きくなりますが、Gen2 MediumとM1 Mediumに差はあまりありません。
200クレジットほどしか消費量は変わらないのにも関わらず、実行時間は4分ほど短縮されています。

かなりテストの数が多くなってくると、テスト分割もおすすめしております。
こちらはParallelismの指定の部分で、使用するコンテナ数を指定します。
実際にテスト分割のコマンドを書いているラインでテストファイルの分割を実行することによって、テストを各コンテナに分散して走らせることが可能になり、より速くテストを完了することができます！

こちらの機能もぜひお試しください！！

```YAML:config.yml
 ui_test_parallel:
    parameters:
      executor:
        type: executor
    executor: << parameters.executor >>
    parallelism: 4
    steps:
      - checkout
      - macos/preboot-simulator:
          device: iPhone 14
          version: "16.4"
      - attach_workspace:
          at: .
      - ruby/install-deps
      - run:
          name: Split tests and run UITests
          command: |
            CLASSNAMES=$(circleci tests glob "UnitTests/*.swift" \
              | sed 's@/@.@g' \
              | sed 's/.swift//' \
              | circleci tests split --split-by=timings --timings-type=classname)
            FASTLANE_ARGS=$(echo $CLASSNAMES | sed -e 's/\./\//g' -e 's/ /,/g')
            bundle exec fastlane unit_tests tests:$FASTLANE_ARGS
      - store_test_results:
          path: fastlane/report.xml
```


# macOSマシーンについてのお知らせ
現在macOS mediumとLargeのリソースクラスを数多くのお客様にご利用いただいておりますが、2023日10月2日をもって、こちらのリソースクラスの提供が終了いたします。
10月2日以降にこちらのリソースクラスを使用するとビルドエラーとなりますので、この機会にGen2またはM1のリソースクラスにアップデートをお願いいたします。
![スクリーンショット 2023-07-28 14.52.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634965/01a02104-1dcf-7f15-3615-3fec312d4aa7.png)
# おわりに
CircleCI M1マシーンいかがでしたでしょうか？
私の担当のお客様の中にもiOSのプロジェクトにおいて40分ビルドにかかっていたジョブを20分まで減らせることができたお客様などもいらっしゃいます。
この機会にぜひM1のmacOSリソースクラスを使い始めてみませんか？
皆様のビルド時間が爆速で改善されることを期待しております！！！

参考URL
[CircleCI M1 Mac パフォーマンス比較](https://tadashi0713.dev/blog/circleci-m1-comparison-ja)
[iOSの自動テスト(iOSシミュレーターを使ったUIテスト)を分割・並列実行しよう](https://circleci.com/ja/blog/ios-parallel-testing/)
[macOS Resource Deprecation Update](https://discuss.circleci.com/t/macos-resource-deprecation-update/46891)