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

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

Aaf94d61dec57d1c3cf2de7c09e472d4?s=47 Daiki Katayama
September 21, 2020

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

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

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

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

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

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

Aaf94d61dec57d1c3cf2de7c09e472d4?s=128

Daiki Katayama

September 21, 2020
Tweet

Transcript

  1. 継続的にアプリ パフォーマンスを計測する iOSDC Japan 2020 kariad

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

    SWET > Automation test iOS team ◦ Software Engineer in Test • ソフトウェアテスト、それを支えるプロセス改善
  3. じめに 今回 発表で 、SWETで取り組んでいるアプリ パフォーマンス計測について話しま す パフォーマンス計測に関する知見 多く なく、試行錯誤しながら作っていったため、失 敗もたくさんあります

    そうした失敗や今 こうしているといった知見を紹介できたらと
  4. アジェンダ 1. なぜパフォーマンス計測が必要な か? 2. iOSアプリにおけるパフォーマンス計測方法 3. 継続して計測する仕組み 作成 4.

    運用してみて 5. これからについて
  5. なぜパフォーマンス計測が必要な か?

  6. アプリ パフォーマンスが悪いと ひとくちにパフォーマンスと言っても様々 • なかなか読み込みが終わらない • 短時間 利用で端末が熱くなる • 動作が重い、カクカク、もっさり

    場合によって パフォーマンスが悪いことでクラッシュも起こりうる
  7. アプリ パフォーマンスが悪いと ユーザーがアプリを快適に利用できない →ユーザー 離脱 可能性 防ぐために リリース前に機能が正しく実装されているかだけで なくパフォー マンス観点でもテストを行い、問題ないかを確認できると良い

  8. iOSアプリにおけるパフォーマンス計測

  9. iOSアプリにおけるパフォーマンス計測 代表的な例 • Instruments • MetricKit • 外部(Apple以外が提供している)サービス ど ような情報が取れるか、ど

    ように情報が取れるか、計測タイミングなど 異なる
  10. Instruments • Xcode 一部として提供されているパフォーマンス計測ツール • どこ パフォーマンスが悪い か分析、特定する機能をサポート • TimeProfiler,

    Leaks, Network等多く テンプレートを持ち様々な角度から 計測 が可能 • 原因 特定 dSYMがあれ 実際 コード どこ 部分かというところまで特定で きる
  11. Instruments Templateが充実していて選ぶだけで簡単に計測ができる

  12. None
  13. Instruments GUIだけで なくCUIからでも計測が可能 instruments -t ${template} -w ${UDID} -l ${timeLimit}

    -D ${fileName}
  14. Instruments GUIだけで なくCUIからでも計測が可能 instruments -t ${template} -w ${UDID} -l ${timeLimit}

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

    環境で計測し、24時間に一回サーバにデータが送られる WWDC セッションによるとMetricKitを用いてTestFlight ベータテスターや実際 ユーザー 手元で何が起こっているかを計測するべきだと述べられている 詳しく知りたい方 WWDC 2020 「What’s new in MetricKit」がおすすめ https://developer.apple.com/videos/play/wwdc2020/10081/
  16. 外部サービス SDKとして組み込んで計測するタイプ • Firebase Performance Monitoring デバイスファームとセットになったサービス • HeadSpin →

    計測できる指標 サービスによりけり
  17. 継続して計測する仕組み

  18. 継続的な計測 • 常に安定したアプリをリリースするに 悪くなってからで 遅い • そ ために継続的にパフォーマンス計測が行える仕組みが必要 ◦ 継続して計測することで改善も実施しやすくなる

    • 毎回手動で実施する 大変な で自動で実施したい
  19. 今回計測したかった内容 Pocochaで視聴者が多い配信で 端末 温度上昇とそれに伴うパフォーマンス低下が 問題になっていた そ ため一定時間負荷をかけ続けたアプリ 状態を配信/視聴画面まで移動してから計 測対象とした •

    計測時間: 30分, 2時間 • 計測内容: CPU使用率と端末 温度(Thermal state) 変化 • 計測タイミング: 毎晩
  20. 継続的な計測で必要と考えたも • 計測ツール • 最新 アプリ • 実機 ◦ 計測する内容にもよるが、端末

    温度など 実機でしか計測ができない • 定期的に実行させるため 環境(CIサービス) • アプリを操作するUIテスト • アプリに負荷をかけるツール
  21. 計測ツール Instrumentsを採用 • すでにパフォーマンスが問題になり始めているということもありリリース前、開発中 に問題ないかを確認したかった • 問題がある場合 早く原因を特定したい ◦ InstrumentsならdSYMがあれ

    原因まで調査できる
  22. 最新 アプリ 毎日 変更に追従した最新 アプリで計測(場合によって 任意 ブランチなど) デバッグ用にdSYMも必要なためCIでArtifactsとして残す必要 さらにInstrumentsで正しく計測するために 以下

    条件を満たす必要がある • コンパイラ 最適化を実際 releaseビルドと合わせる • development 証明書でsignしている
  23. 最新 アプリ コンパイラ 最適化 問題 • Xcode デフォルト 設定で debugビルドとreleaseビルドで最適化

    設定 異 なっている • 最適化 差異がパフォーマンス計測に影響がでる可能性がある • 実際にユーザが利用するreleaseビルドと同等 最適化がされたアプリで計測する 必要がある • WWDC 2019 Getting Started with Instrumentsセッションが参考になる ◦ https://developer.apple.com/videos/play/wwdc2019/411/
  24. 最新 アプリ signする証明書 問題 • Instrumentsで計測するために development certificateでsignしたも でなくて いけない(配布用で

    計測できない) release 最適化設定を利用しながらdevelopmentでsignが必要
  25. 最新 アプリ ipa resign • ipaに対して証明書を付け替えることができる • releaseでビルドしたipaに対してdevelopment 証明書でresignできる •

    fastlane resignを利用 ◦ https://docs.fastlane.tools/actions/resign/
  26. 最新 アプリ 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" )
  27. 最新 アプリ 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も変えられる
  28. 実機 Thermal stateを計測するために実機で 計測が必要 • 自前で管理 コストが高い ◦ テストが走っているタイミングで他 テストが走らないようにする排他制御が必要

    ◦ OS バージョン管理 ◦ 場所も取る ◦ 問題が発生したときに出社が必要
  29. 実機 クラウド型 デバイスファーム Web等から実際 実機と同じようにアクセス、操作できるサービス • AWS Device Farm •

    Remote Testkit • HeadSpin
  30. HeadSpin 様々なパフォーマンス計測もできるデバイスファーム 端末単位 契約で端末を他社と共有すること ない • Xcodeから直接Runができる • Wi-Fiだけでなく特定 SIMで4G回線で

    利用もできる • 実機でできる大体 こと できる • AppiumサーバーがHeadSpin側で用意されている 今回計測 Instrumentsを使うことにした でHeadSpin 機能 使っていない(将来的 に計測項目が増えた際に使いたいと 思っている)
  31. HeadSpin Appiumについて 補足 Appiumクライアント Appiumサーバー Web driver agent テストスクリプト テスト対象アプリ

    端末 Appium動かすに ここが必要
  32. HeadSpin

  33. HeadSpin APIも充実していて例え • ipa インストール、アンインストール • スクリーンショット 撮影 • デバイス

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

    Web Driver URLをセットするだけで利用できる • Appium バージョンもCapabilityから指定できる(インストールされていない場合 お願いしたらすぐ対応してくれる)
  35. HeadSpin Appium以外から利用する場合 • HeadSpin CLIを使ってbridgeする • XcodeからRunできる、Instrumentsで計測もできる

  36. CI 今回 計測で 2種類 用途がある • 計測対象 アプリをビルド、resignする • 計測を行う(負荷ツールを動かす)

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

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

    XCUITest HeadSpinを利用する予定だった でAppiumサーバーを用意する必要がなく、Appium が相性が良かった AppiumからInstrumentsを利用することもできた も◯
  39. 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' )
  40. Appium Capabilityで 注意点 • 実機 場合 bundleId 指定が必須 • 待ちが発生するためnewCommandTimeout

    設定をしてTimeoutを防ぐ • HeadSpin Appiumサーバーを利用する場合 serverUrlに設定する
  41. アプリに負荷をかけるツール 必ずしも必要なも と 限らないが、今回 要件で 必要だった • SWET 他チーム(Goチーム) メンバーと協力して作成

    • 変更が入った場合でも常に最新 も を利用するためGitHub Release Assets からDLできるように
  42. こ 構成で起きた問題 必要なも すべて揃った、後 組み合わせるだけ... そう上手いこといくわけ なかった 起きた問題 一例として •

    Appium server 問題 • Instruments データ取得 問題
  43. Appium server 問題 最初Appium server HeadSpin も を使う想定だった いくつか 理由からAppium

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

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

    知らなかった) そ ため、結果 確認 Instruments appを開いてGUIで結果を確認する必要がある • 30分 計測ともなるとファイルサイズ(150〜200MB程度)も大きく、開く に時間が かかる ◦ 1分くらいかかることも ... • 毎回手動で結果を確認する かなり面倒 *TraceUtility(https://github.com/Qusic/TraceUtility )
  46. Nominal → Fair → Serious → Critical

  47. Nominal → Fair → Serious → Critical 各state 開始時間と終了時間が表示される

  48. CPU使用率 推移 グラフで み表示される 詳細に表示される ど 処理が何%CPUを利用しているか グラフ 最大値がそ 回

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

    ンショットを撮影、Slackに投稿させた • Thermal stateについて 文字列で 情報も取れるためSeriousまで行ったら失敗 させるといったこともできる • CPU使用率について 厳しかった
  50. Instruments 問題 Slackへ 投稿

  51. 検討した上で 今回 構成 • 計測ツール: Instruments(Appiumから利用) • 最新 アプリ: Bitriseでビルド

    • 実機: HeadSpin • CI(計測): Jenkins • アプリ操作用 UITestフレームワーク: Appium • 負荷をかけるツール: お手製 複数 ツールに跨っていて終わったら次、といった感じにピタゴラスイッチみたいにに なってしまった
  52. Bitrise 1. releaseビルドでipaを生成 2. development証明書でresign

  53. Bitrise 5. Jenkins jobトリガーAPIを実行 Jenkins 3. dSYMをArtifacts化 HeadSpin 4. HeadSpin

    APIを使ってipaを配布
  54. Bitrise 7. 負荷ツール DL、Appiumサー バー 起動等 準備 Jenkins HeadSpin 6.

    HeadSpin 端末に接続 Appium サーバー
  55. Bitrise 8. 計測開始 9. 計測完了 Jenkins HeadSpin Appium サーバー

  56. Bitrise 10. traceファイルをXCUITestで操作 して結果を取得 Jenkins HeadSpin Appium サーバー trace ファイル

  57. Bitrise 11. traceファイル Artifacts化 12. 結果 Slackへ 投稿 Jenkins HeadSpin

    Appium サーバー
  58. 処理 流れ(概要) 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化
  59. そしてJenkinsfileが長くなる 処理が多くJenkinsfileがどうしても長くなってしまう で可読性等 が低い 前述 流れ 中でさらにいろいろやっている デバッグもしづらくメンテナンスがしづらい問題 ある

  60. 実際に運用してみて

  61. 実際に運用してみて 実際に運用をしていく中で想定していた問題や、新たな問題が発生 • Appium 不安定さ • 実行パターン 増加 • 季節

    • インカメラへ 利用 • 結果確認 方法
  62. Appium 不安定さ 負荷をかけ続けた状態で一定時間経つと、connection errorが発生する 最後 最後でInstrumentsが完了できないということも • 本来 使い方で ない

    で仕方が無いといえ 仕方がない かもしれない • Appium serverとクライアントで通信をしながら操作しているため起きた問題かも • 詳細な原因 わからずじまい
  63. Appium 不安定さ 採用理由がHeadSpinでAppiumサーバーが用意されていて便利だったから HeadSpin Appium serverを利用しなくなった時点でAppiumである必要性がほぼなく なっていた → であれ XCUITestでもいい

    で ないか • 現在 XCUITestに移行済み • InstrumentsもCUIで実行している
  64. 実行パターン 増加 最初 1パターンx2(30分, 2時間)で 計測 新機能追加に伴う色々な状態で 計測が求められるように • 端末温度が上昇するためそ

    まま次を計測してしまうと、前回 結果に引きづられ る正しい計測ができない • 環境にもよるが、最低でも30分 間隔を空けないと実機で前回 影響を受けずに 正しい計測 できない
  65. 実行パターン 計測 クールタイム 計測 計測 クールタイム 計測 端末A 端末B 端末数を増やして対応(ど

    端末が何分待ったかという調整 必要)
  66. 季節 外部気温 変化によるThermal stateへ 影響 • 実装時 冬〜春 • 運用中に夏に

    • 同じ条件でも外部気温 影響でより やく端末温度 上昇が起きた ただこれ ユーザーにも同じことが言えるため、夏でも問題ないようにパフォーマンスを 良くするべき
  67. インカメラ 利用 計測パターンでインカメラに人 顔を写した状態で計測する必要が出てきた HeadSpin 場合 同一 端末を契約単位で利用している インカメラに特定 画像を写し続けるといった特別な対応も行ってくれる

    → HeadSpin おかげで解決
  68. 結果確認フロー 問題 Slackに投稿していると いえCPU使用率に関して 実際に開いてみないとわかりづら い問題がや りある • 結果として毎回100MB超え ファイルをDLして、起動に時間がかかり...を手動で

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

    • 実機: HeadSpin(端末数が増えた) • CI(計測): Jenkins • アプリ操作用 UITestフレームワーク: XCUITest • 負荷をかけるツール: お手製 そ 他細かいところ 調整している
  70. これから 展望

  71. xctrace Xcode12からInstrumentsコマンドがdeprecatedとなりxctraceが追加された • 基本的にInstrumentsコマンドでできていたこと できる • traceファイルからXML形式でデータが取得可能 • Thermal stateが取得できること

    確認済み • CPU使用率について 現時点で 難しいかもしれない
  72. Bitrise(MacStadium)へ 移行 当初2時間で 計測も考えていたが、今 30分 計測 みに変わった • 結果として90分制限に縛られなくなったためBitriseへ 移行も考えている

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

    Big Queryにデータを入れてData studio等で可視化を検討している こ パフォーマンス計測もそこに合わせてデータを可視化したい
  74. さいごに 今回紹介した計測方法 あくまでも一例 アプリ 特性や何を計測したいかでも変わってくる アプリ 特性にもよるが、パフォーマンスがまだ問題になっていない であれ MetricKitから導入してみる がいいかもしれない

    そこから改善 サイクルを回していきましょう
  75. DeNA Tech Twitter アカウントで 、 DeNA エンジニアリングに関する 登壇資料やブログを紹介しています! 後日ブログで紹介しきれなかったところを書く でそ

    告知もあります
  76. ありがとうございました!