Upgrade to Pro — share decks privately, control downloads, hide ads and more …

アプリのパフォーマンスを継続的に計測する

 アプリのパフォーマンスを継続的に計測する

ユーザーにアプリを快適に使ってもらうためには、機能が動くだけでなくアプリのパフォーマンスも重要です。
端末が熱くて持てない、動作がカクカクするなど快適に動かないアプリは、ユーザー体験を著しくそこなってしまい、ユーザの離脱にもつながっていきます。

このような事態にならないためにも、アプリのパフォーマンスの計測を継続的におこない、
問題がある箇所を見つけて適切に対処すること重要です。

iOSアプリ開発ではInstrumentsなどを用いてパフォーマンスを計測することができますが、手動で計測しつづけるのは困難です。
今回は自分たちでCPU使用率と端末温度の計測を継続的に実施する仕組みをInstrumentsを用いて作成しました。

これらの仕組みを用意するために、CI/CDサービスをどうするか、どのように操作をし続けるかなど、様々な課題がありました。
また、運用していく中では、Instrumentsのデータの見づらさや想定外のクラッシュなどいくつもの問題が発生しました。

本トークでは、実際にiOSアプリケーションのCPU使用率と端末温度を継続的に計測する仕組みを作成し、運用している環境をどう実現したかに加えて「乗り越えた課題」、そして「残る課題と今後」についてより詳しく話をします。

Daiki Katayama

September 21, 2020
Tweet

More Decks by Daiki Katayama

Other Decks in Programming

Transcript

  1. 自己紹介 • kariad / 片山大樹 / @kariad_uu • DeNA >

    SWET > Automation test iOS team ◦ Software Engineer in Test • ソフトウェアテスト、それを支えるプロセス改善
  2. Instruments • Xcode 一部として提供されているパフォーマンス計測ツール • どこ パフォーマンスが悪い か分析、特定する機能をサポート • TimeProfiler,

    Leaks, Network等多く テンプレートを持ち様々な角度から 計測 が可能 • 原因 特定 dSYMがあれ 実際 コード どこ 部分かというところまで特定で きる
  3. Instruments GUIだけで なくCUIからでも計測が可能 instruments -t ${template} -w ${UDID} -l ${timeLimit}

    -D ${fileName} ※保存時に少し時間がかかる で注意 template名(e.g. Time Profiler) 計測に利用する端末 UDID 計測時間 上限(ms) 保存時 ファイル名 (xxx.trace)
  4. MetricKit • iOS13から利用可能 • 実際にコードに埋め込んでデバイス上 情報を取得できる • 起動時間、CPU使用時間、バッテリー消費量、クラッシュなど • ユーザ

    環境で計測し、24時間に一回サーバにデータが送られる WWDC セッションによるとMetricKitを用いてTestFlight ベータテスターや実際 ユーザー 手元で何が起こっているかを計測するべきだと述べられている 詳しく知りたい方 WWDC 2020 「What’s new in MetricKit」がおすすめ https://developer.apple.com/videos/play/wwdc2020/10081/
  5. 継続的な計測で必要と考えたも • 計測ツール • 最新 アプリ • 実機 ◦ 計測する内容にもよるが、端末

    温度など 実機でしか計測ができない • 定期的に実行させるため 環境(CIサービス) • アプリを操作するUIテスト • アプリに負荷をかけるツール
  6. 最新 アプリ コンパイラ 最適化 問題 • Xcode デフォルト 設定で debugビルドとreleaseビルドで最適化

    設定 異 なっている • 最適化 差異がパフォーマンス計測に影響がでる可能性がある • 実際にユーザが利用するreleaseビルドと同等 最適化がされたアプリで計測する 必要がある • WWDC 2019 Getting Started with Instrumentsセッションが参考になる ◦ https://developer.apple.com/videos/play/wwdc2019/411/
  7. 最新 アプリ fastlane resign resign( ipa: ipa_path, signing_identity: "iPhone Developer:

    Xxxxxx Xxxxxxx(FFFFFFFFF)", provisioning_profile: { "com.swet.app" => provisioning_profile_path, "com.swet.app.notificationservice" => provisioning_profile_notification_path }, display_name: "SWET Debug" )
  8. 最新 アプリ fastlane resign resign( ipa: ipa_path, signing_identity: "iPhone Developer:

    Xxxxxx Xxxxxxx(FFFFFFFFF)", provisioning_profile: { "com.swet.app" => provisioning_profile_path, "com.swet.app.notificationservice" => provisioning_profile_notification_path }, display_name: "SWET Debug" ) resign後 identity(今回 例で release→development な でdevelopment を記載) 左側に今signしているBundle identifier(今回 release) 右側にresignするProvisioning profile path 後からわかるようにdisplay nameも変えられる
  9. HeadSpin 様々なパフォーマンス計測もできるデバイスファーム 端末単位 契約で端末を他社と共有すること ない • Xcodeから直接Runができる • Wi-Fiだけでなく特定 SIMで4G回線で

    利用もできる • 実機でできる大体 こと できる • AppiumサーバーがHeadSpin側で用意されている 今回計測 Instrumentsを使うことにした でHeadSpin 機能 使っていない(将来的 に計測項目が増えた際に使いたいと 思っている)
  10. HeadSpin APIも充実していて例え • ipa インストール、アンインストール • スクリーンショット 撮影 • デバイス

    ロック、アンロック • OSアップデート ポップアップを消す 等々、他にも色々ある
  11. HeadSpin Appiumから利用する場合 • Capability server_urlにHeadSpin側に表示されるURLをセットするだけで Appiumサーバーを立てずに利用できる(UDID等 必要) • Appium DesktopからもHeadSpin

    Web Driver URLをセットするだけで利用できる • Appium バージョンもCapabilityから指定できる(インストールされていない場合 お願いしたらすぐ対応してくれる)
  12. CI 今回 計測で 2種類 用途がある • 計測対象 アプリをビルド、resignする • 計測を行う(負荷ツールを動かす)

    元々Bitriseを利用していた でビルド Bitriseで問題ない 計測 最大2時間を想定していたためBitriseで 不可能(現時点 最大 90分) → 色々やりたいと考えるとひとまず選択肢として Jenkins
  13. CI Jenkins • Jenkins自体 管理が必要 → SWET CI/CDチームが管理してくれているJenkinsに相乗り Xcode 新しいバージョンも簡単にインストールできる仕組みが整っている

    (Jenkinsに詳しいメンバーが周りにいる で困ったら気軽に質問できる) ただし最終的に 脱Jenkinsを考えて いる
  14. アプリ操作用 UITestフレームワーク 目的 画面までアプリ 操作が必要 • Appium x Ruby(RSpec) •

    XCUITest HeadSpinを利用する予定だった でAppiumサーバーを用意する必要がなく、Appium が相性が良かった AppiumからInstrumentsを利用することもできた も◯
  15. Appium Insturmentsで 計測がAppium コード経由で実行することができる # Rubyで 例 # 計測開始 @driver.start_performance_record(

    timeout: ENV['TIMEOUT'], profile_name: 'Time Profiler' ) # 計測完了 @driver.get_performance_record( save_file_path: "fine_name", profile_name: 'Time Profiler' )
  16. Appium Capabilityで 注意点 • 実機 場合 bundleId 指定が必須 • 待ちが発生するためnewCommandTimeout

    設定をしてTimeoutを防ぐ • HeadSpin Appiumサーバーを利用する場合 serverUrlに設定する
  17. Appium server 問題 最初Appium server HeadSpin も を使う想定だった いくつか 理由からAppium

    serverをJenkins上で持つ形に • Xcode バージョン • traceファイル 保存先 Appium serverをHeadSpin側 も を利用するということ 、Instruments バージョン (Xcode バージョン)も向こうに依存してしまう 新しくしたりビルドと合わせたりと柔軟性がほしかった
  18. Appium server 問題 traceファイル 保存先 Instrumentsで 計測自体 HeadSpin サーバーで実行されている →

    traceファイルを転送する必要がある • 転送先を考える必要性 ◦ 転送 仕組み自体 Appiumで実装されている Xcode バージョン 問題とを考慮してJenkins上でAppium serverを建てる方法を採 用 → HeadSpin 端末 み 利用に
  19. Instruments 問題 Instruments 問題点として計測結果を定量的な数値で取得する方法がない (実際に ある程度とれるも * あったがこ 時点で 存在

    知らなかった) そ ため、結果 確認 Instruments appを開いてGUIで結果を確認する必要がある • 30分 計測ともなるとファイルサイズ(150〜200MB程度)も大きく、開く に時間が かかる ◦ 1分くらいかかることも ... • 毎回手動で結果を確認する かなり面倒 *TraceUtility(https://github.com/Qusic/TraceUtility )
  20. CPU使用率 推移 グラフで み表示される 詳細に表示される ど 処理が何%CPUを利用しているか グラフ 最大値がそ 回

    一番使用率が高い値になってしまう (全く同じグラフだったとしても同じ使用率と 限らない)
  21. Instruments 問題 XCUITestを用いた強引な解決策 • XCUITest Instrumentsを操作することもできる • XCUITestでtraceファイルを開いてThermal stateとCPU使用率 部分でスクリー

    ンショットを撮影、Slackに投稿させた • Thermal stateについて 文字列で 情報も取れるためSeriousまで行ったら失敗 させるといったこともできる • CPU使用率について 厳しかった
  22. 検討した上で 今回 構成 • 計測ツール: Instruments(Appiumから利用) • 最新 アプリ: Bitriseでビルド

    • 実機: HeadSpin • CI(計測): Jenkins • アプリ操作用 UITestフレームワーク: Appium • 負荷をかけるツール: お手製 複数 ツールに跨っていて終わったら次、といった感じにピタゴラスイッチみたいにに なってしまった
  23. 処理 流れ(概要) 1. Bitriseでreleaseビルドでipaを作成 2. ipaに対してdevelopment証明書でresign 3. 最終的なipaをHeadSpinにAPI経由で配布、dSYMをArtifacts化 4. BitriseからJenkins

    トリガー実行 5. Jenkinsで負荷ツール DL、起動、HeadSpinへ 接続等 準備 6. 計測開始 7. 計測完了 8. 結果 traceファイルをXCUITestを用いて結果 SSを撮影 9. 結果をSlackに通知、traceファイル等 Artifacts化
  24. Appium 不安定さ 負荷をかけ続けた状態で一定時間経つと、connection errorが発生する 最後 最後でInstrumentsが完了できないということも • 本来 使い方で ない

    で仕方が無いといえ 仕方がない かもしれない • Appium serverとクライアントで通信をしながら操作しているため起きた問題かも • 詳細な原因 わからずじまい
  25. 実行パターン 増加 最初 1パターンx2(30分, 2時間)で 計測 新機能追加に伴う色々な状態で 計測が求められるように • 端末温度が上昇するためそ

    まま次を計測してしまうと、前回 結果に引きづられ る正しい計測ができない • 環境にもよるが、最低でも30分 間隔を空けないと実機で前回 影響を受けずに 正しい計測 できない
  26. 季節 外部気温 変化によるThermal stateへ 影響 • 実装時 冬〜春 • 運用中に夏に

    • 同じ条件でも外部気温 影響でより やく端末温度 上昇が起きた ただこれ ユーザーにも同じことが言えるため、夏でも問題ないようにパフォーマンスを 良くするべき
  27. 結果確認フロー 問題 Slackに投稿していると いえCPU使用率に関して 実際に開いてみないとわかりづら い問題がや りある • 結果として毎回100MB超え ファイルをDLして、起動に時間がかかり...を手動で

    チェックする必要があった • CPU使用率に関して GUIですら明確な数値が出せない • グラフも最大値に合わせて上下してしまう ◦ 定量的に判断が難しい • まだ未解決
  28. 運用した結果 変更 • 計測ツール: Instruments CLI • 最新 アプリ: Bitriseでビルド

    • 実機: HeadSpin(端末数が増えた) • CI(計測): Jenkins • アプリ操作用 UITestフレームワーク: XCUITest • 負荷をかけるツール: お手製 そ 他細かいところ 調整している
  29. Bitrise(MacStadium)へ 移行 当初2時間で 計測も考えていたが、今 30分 計測 みに変わった • 結果として90分制限に縛られなくなったためBitriseへ 移行も考えている

    • Instrumentsで 計測にそれなり スペックがないと不安定な でそこだけ心配 一方でJenkinsもオンプレからMacStadiumへ移行している • Mac miniを借りれるクラウド • MacStadiumだと再起動が出社なしで可能
  30. 他項目 計測 今計測している項目以外でも計測したいも が出てきている そ ため現在、FPSなど 新たな項目で 計測 準備をしている そちら

    Big Queryにデータを入れてData studio等で可視化を検討している こ パフォーマンス計測もそこに合わせてデータを可視化したい