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. 継続的にアプリ
    パフォーマンスを計測する
    iOSDC Japan 2020
    kariad

    View Slide

  2. 自己紹介
    ● kariad / 片山大樹 / @kariad_uu
    ● DeNA > SWET > Automation test iOS team
    ○ Software Engineer in Test
    ● ソフトウェアテスト、それを支えるプロセス改善

    View Slide

  3. じめに
    今回 発表で 、SWETで取り組んでいるアプリ パフォーマンス計測について話しま

    パフォーマンス計測に関する知見 多く なく、試行錯誤しながら作っていったため、失
    敗もたくさんあります
    そうした失敗や今 こうしているといった知見を紹介できたらと

    View Slide

  4. アジェンダ
    1. なぜパフォーマンス計測が必要な か?
    2. iOSアプリにおけるパフォーマンス計測方法
    3. 継続して計測する仕組み 作成
    4. 運用してみて
    5. これからについて

    View Slide

  5. なぜパフォーマンス計測が必要な か?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  10. Instruments
    ● Xcode 一部として提供されているパフォーマンス計測ツール
    ● どこ パフォーマンスが悪い か分析、特定する機能をサポート
    ● TimeProfiler, Leaks, Network等多く テンプレートを持ち様々な角度から 計測
    が可能
    ● 原因 特定 dSYMがあれ 実際 コード どこ 部分かというところまで特定で
    きる

    View Slide

  11. Instruments
    Templateが充実していて選ぶだけで簡単に計測ができる

    View Slide

  12. View Slide

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

    View Slide

  14. Instruments
    GUIだけで なくCUIからでも計測が可能
    instruments -t ${template} -w ${UDID} -l ${timeLimit} -D ${fileName}
    ※保存時に少し時間がかかる で注意
    template名(e.g. Time Profiler)
    計測に利用する端末 UDID
    計測時間 上限(ms)
    保存時 ファイル名 (xxx.trace)

    View Slide

  15. MetricKit
    ● iOS13から利用可能
    ● 実際にコードに埋め込んでデバイス上 情報を取得できる
    ● 起動時間、CPU使用時間、バッテリー消費量、クラッシュなど
    ● ユーザ 環境で計測し、24時間に一回サーバにデータが送られる
    WWDC セッションによるとMetricKitを用いてTestFlight ベータテスターや実際
    ユーザー 手元で何が起こっているかを計測するべきだと述べられている
    詳しく知りたい方 WWDC 2020 「What’s new in MetricKit」がおすすめ
    https://developer.apple.com/videos/play/wwdc2020/10081/

    View Slide

  16. 外部サービス
    SDKとして組み込んで計測するタイプ
    ● Firebase Performance Monitoring
    デバイスファームとセットになったサービス
    ● HeadSpin
    → 計測できる指標 サービスによりけり

    View Slide

  17. 継続して計測する仕組み

    View Slide

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

    View Slide

  19. 今回計測したかった内容
    Pocochaで視聴者が多い配信で 端末 温度上昇とそれに伴うパフォーマンス低下が
    問題になっていた
    そ ため一定時間負荷をかけ続けたアプリ 状態を配信/視聴画面まで移動してから計
    測対象とした
    ● 計測時間: 30分, 2時間
    ● 計測内容: CPU使用率と端末 温度(Thermal state) 変化
    ● 計測タイミング: 毎晩

    View Slide

  20. 継続的な計測で必要と考えたも
    ● 計測ツール
    ● 最新 アプリ
    ● 実機
    ○ 計測する内容にもよるが、端末 温度など 実機でしか計測ができない
    ● 定期的に実行させるため 環境(CIサービス)
    ● アプリを操作するUIテスト
    ● アプリに負荷をかけるツール

    View Slide

  21. 計測ツール
    Instrumentsを採用
    ● すでにパフォーマンスが問題になり始めているということもありリリース前、開発中
    に問題ないかを確認したかった
    ● 問題がある場合 早く原因を特定したい
    ○ InstrumentsならdSYMがあれ 原因まで調査できる

    View Slide

  22. 最新 アプリ
    毎日 変更に追従した最新 アプリで計測(場合によって 任意 ブランチなど)
    デバッグ用にdSYMも必要なためCIでArtifactsとして残す必要
    さらにInstrumentsで正しく計測するために 以下 条件を満たす必要がある
    ● コンパイラ 最適化を実際 releaseビルドと合わせる
    ● development 証明書でsignしている

    View Slide

  23. 最新 アプリ
    コンパイラ 最適化 問題
    ● Xcode デフォルト 設定で debugビルドとreleaseビルドで最適化 設定 異
    なっている
    ● 最適化 差異がパフォーマンス計測に影響がでる可能性がある
    ● 実際にユーザが利用するreleaseビルドと同等 最適化がされたアプリで計測する
    必要がある
    ● WWDC 2019 Getting Started with Instrumentsセッションが参考になる
    ○ https://developer.apple.com/videos/play/wwdc2019/411/

    View Slide

  24. 最新 アプリ
    signする証明書 問題
    ● Instrumentsで計測するために development certificateでsignしたも でなくて
    いけない(配布用で 計測できない)
    release 最適化設定を利用しながらdevelopmentでsignが必要

    View Slide

  25. 最新 アプリ
    ipa resign
    ● ipaに対して証明書を付け替えることができる
    ● releaseでビルドしたipaに対してdevelopment 証明書でresignできる
    ● fastlane resignを利用
    ○ https://docs.fastlane.tools/actions/resign/

    View Slide

  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"
    )

    View Slide

  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も変えられる

    View Slide

  28. 実機
    Thermal stateを計測するために実機で 計測が必要
    ● 自前で管理 コストが高い
    ○ テストが走っているタイミングで他 テストが走らないようにする排他制御が必要
    ○ OS バージョン管理
    ○ 場所も取る
    ○ 問題が発生したときに出社が必要

    View Slide

  29. 実機
    クラウド型 デバイスファーム
    Web等から実際 実機と同じようにアクセス、操作できるサービス
    ● AWS Device Farm
    ● Remote Testkit
    ● HeadSpin

    View Slide

  30. HeadSpin
    様々なパフォーマンス計測もできるデバイスファーム
    端末単位 契約で端末を他社と共有すること ない
    ● Xcodeから直接Runができる
    ● Wi-Fiだけでなく特定 SIMで4G回線で 利用もできる
    ● 実機でできる大体 こと できる
    ● AppiumサーバーがHeadSpin側で用意されている
    今回計測 Instrumentsを使うことにした でHeadSpin 機能 使っていない(将来的
    に計測項目が増えた際に使いたいと 思っている)

    View Slide

  31. HeadSpin
    Appiumについて 補足
    Appiumクライアント Appiumサーバー Web driver agent
    テストスクリプト テスト対象アプリ
    端末
    Appium動かすに ここが必要

    View Slide

  32. HeadSpin

    View Slide

  33. HeadSpin
    APIも充実していて例え
    ● ipa インストール、アンインストール
    ● スクリーンショット 撮影
    ● デバイス ロック、アンロック
    ● OSアップデート ポップアップを消す
    等々、他にも色々ある

    View Slide

  34. HeadSpin
    Appiumから利用する場合
    ● Capability server_urlにHeadSpin側に表示されるURLをセットするだけで
    Appiumサーバーを立てずに利用できる(UDID等 必要)
    ● Appium DesktopからもHeadSpin Web Driver URLをセットするだけで利用できる
    ● Appium バージョンもCapabilityから指定できる(インストールされていない場合
    お願いしたらすぐ対応してくれる)

    View Slide

  35. HeadSpin
    Appium以外から利用する場合
    ● HeadSpin CLIを使ってbridgeする
    ● XcodeからRunできる、Instrumentsで計測もできる

    View Slide

  36. CI
    今回 計測で 2種類 用途がある
    ● 計測対象 アプリをビルド、resignする
    ● 計測を行う(負荷ツールを動かす)
    元々Bitriseを利用していた でビルド Bitriseで問題ない
    計測 最大2時間を想定していたためBitriseで 不可能(現時点 最大 90分)
    → 色々やりたいと考えるとひとまず選択肢として Jenkins

    View Slide

  37. CI
    Jenkins
    ● Jenkins自体 管理が必要
    → SWET CI/CDチームが管理してくれているJenkinsに相乗り
    Xcode 新しいバージョンも簡単にインストールできる仕組みが整っている
    (Jenkinsに詳しいメンバーが周りにいる で困ったら気軽に質問できる)
    ただし最終的に 脱Jenkinsを考えて いる

    View Slide

  38. アプリ操作用 UITestフレームワーク
    目的 画面までアプリ 操作が必要
    ● Appium x Ruby(RSpec)
    ● XCUITest
    HeadSpinを利用する予定だった でAppiumサーバーを用意する必要がなく、Appium
    が相性が良かった
    AppiumからInstrumentsを利用することもできた も◯

    View Slide

  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'
    )

    View Slide

  40. Appium
    Capabilityで 注意点
    ● 実機 場合 bundleId 指定が必須
    ● 待ちが発生するためnewCommandTimeout 設定をしてTimeoutを防ぐ
    ● HeadSpin Appiumサーバーを利用する場合 serverUrlに設定する

    View Slide

  41. アプリに負荷をかけるツール
    必ずしも必要なも と 限らないが、今回 要件で 必要だった
    ● SWET 他チーム(Goチーム) メンバーと協力して作成
    ● 変更が入った場合でも常に最新 も を利用するためGitHub Release Assets
    からDLできるように

    View Slide

  42. こ 構成で起きた問題
    必要なも すべて揃った、後 組み合わせるだけ...
    そう上手いこといくわけ なかった
    起きた問題 一例として
    ● Appium server 問題
    ● Instruments データ取得 問題

    View Slide

  43. Appium server 問題
    最初Appium server HeadSpin も を使う想定だった
    いくつか 理由からAppium serverをJenkins上で持つ形に
    ● Xcode バージョン
    ● traceファイル 保存先
    Appium serverをHeadSpin側 も を利用するということ 、Instruments バージョン
    (Xcode バージョン)も向こうに依存してしまう
    新しくしたりビルドと合わせたりと柔軟性がほしかった

    View Slide

  44. Appium server 問題
    traceファイル 保存先
    Instrumentsで 計測自体 HeadSpin サーバーで実行されている
    → traceファイルを転送する必要がある
    ● 転送先を考える必要性
    ○ 転送 仕組み自体 Appiumで実装されている
    Xcode バージョン 問題とを考慮してJenkins上でAppium serverを建てる方法を採

    → HeadSpin 端末 み 利用に

    View Slide

  45. Instruments 問題
    Instruments 問題点として計測結果を定量的な数値で取得する方法がない
    (実際に ある程度とれるも * あったがこ 時点で 存在 知らなかった)
    そ ため、結果 確認 Instruments appを開いてGUIで結果を確認する必要がある
    ● 30分 計測ともなるとファイルサイズ(150〜200MB程度)も大きく、開く に時間が
    かかる
    ○ 1分くらいかかることも ...
    ● 毎回手動で結果を確認する かなり面倒
    *TraceUtility(https://github.com/Qusic/TraceUtility
    )

    View Slide

  46. Nominal → Fair → Serious → Critical

    View Slide

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

    View Slide

  48. CPU使用率 推移 グラフで み表示される
    詳細に表示される ど 処理が何%CPUを利用しているか
    グラフ 最大値がそ 回 一番使用率が高い値になってしまう
    (全く同じグラフだったとしても同じ使用率と 限らない)

    View Slide

  49. Instruments 問題
    XCUITestを用いた強引な解決策
    ● XCUITest Instrumentsを操作することもできる
    ● XCUITestでtraceファイルを開いてThermal stateとCPU使用率 部分でスクリー
    ンショットを撮影、Slackに投稿させた
    ● Thermal stateについて 文字列で 情報も取れるためSeriousまで行ったら失敗
    させるといったこともできる
    ● CPU使用率について 厳しかった

    View Slide

  50. Instruments 問題
    Slackへ 投稿

    View Slide

  51. 検討した上で 今回 構成
    ● 計測ツール: Instruments(Appiumから利用)
    ● 最新 アプリ: Bitriseでビルド
    ● 実機: HeadSpin
    ● CI(計測): Jenkins
    ● アプリ操作用 UITestフレームワーク: Appium
    ● 負荷をかけるツール: お手製
    複数 ツールに跨っていて終わったら次、といった感じにピタゴラスイッチみたいにに
    なってしまった

    View Slide

  52. Bitrise
    1. releaseビルドでipaを生成
    2. development証明書でresign

    View Slide

  53. Bitrise
    5. Jenkins jobトリガーAPIを実行
    Jenkins
    3. dSYMをArtifacts化
    HeadSpin
    4. HeadSpin APIを使ってipaを配布

    View Slide

  54. Bitrise
    7. 負荷ツール DL、Appiumサー
    バー 起動等 準備
    Jenkins
    HeadSpin
    6. HeadSpin 端末に接続
    Appium
    サーバー

    View Slide

  55. Bitrise
    8. 計測開始
    9. 計測完了
    Jenkins
    HeadSpin
    Appium
    サーバー

    View Slide

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

    View Slide

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

    View Slide

  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化

    View Slide

  59. そしてJenkinsfileが長くなる
    処理が多くJenkinsfileがどうしても長くなってしまう で可読性等
    が低い
    前述 流れ 中でさらにいろいろやっている
    デバッグもしづらくメンテナンスがしづらい問題 ある

    View Slide

  60. 実際に運用してみて

    View Slide

  61. 実際に運用してみて
    実際に運用をしていく中で想定していた問題や、新たな問題が発生
    ● Appium 不安定さ
    ● 実行パターン 増加
    ● 季節
    ● インカメラへ 利用
    ● 結果確認 方法

    View Slide

  62. Appium 不安定さ
    負荷をかけ続けた状態で一定時間経つと、connection errorが発生する
    最後 最後でInstrumentsが完了できないということも
    ● 本来 使い方で ない で仕方が無いといえ 仕方がない かもしれない
    ● Appium serverとクライアントで通信をしながら操作しているため起きた問題かも
    ● 詳細な原因 わからずじまい

    View Slide

  63. Appium 不安定さ
    採用理由がHeadSpinでAppiumサーバーが用意されていて便利だったから
    HeadSpin Appium serverを利用しなくなった時点でAppiumである必要性がほぼなく
    なっていた
    → であれ XCUITestでもいい で ないか
    ● 現在 XCUITestに移行済み
    ● InstrumentsもCUIで実行している

    View Slide

  64. 実行パターン 増加
    最初 1パターンx2(30分, 2時間)で 計測
    新機能追加に伴う色々な状態で 計測が求められるように
    ● 端末温度が上昇するためそ まま次を計測してしまうと、前回 結果に引きづられ
    る正しい計測ができない
    ● 環境にもよるが、最低でも30分 間隔を空けないと実機で前回 影響を受けずに
    正しい計測 できない

    View Slide

  65. 実行パターン
    計測 クールタイム 計測
    計測 クールタイム 計測
    端末A
    端末B
    端末数を増やして対応(ど 端末が何分待ったかという調整 必要)

    View Slide

  66. 季節
    外部気温 変化によるThermal stateへ 影響
    ● 実装時 冬〜春
    ● 運用中に夏に
    ● 同じ条件でも外部気温 影響でより やく端末温度 上昇が起きた
    ただこれ ユーザーにも同じことが言えるため、夏でも問題ないようにパフォーマンスを
    良くするべき

    View Slide

  67. インカメラ 利用
    計測パターンでインカメラに人 顔を写した状態で計測する必要が出てきた
    HeadSpin 場合 同一 端末を契約単位で利用している
    インカメラに特定 画像を写し続けるといった特別な対応も行ってくれる
    → HeadSpin おかげで解決

    View Slide

  68. 結果確認フロー 問題
    Slackに投稿していると いえCPU使用率に関して 実際に開いてみないとわかりづら
    い問題がや りある
    ● 結果として毎回100MB超え ファイルをDLして、起動に時間がかかり...を手動で
    チェックする必要があった
    ● CPU使用率に関して GUIですら明確な数値が出せない
    ● グラフも最大値に合わせて上下してしまう
    ○ 定量的に判断が難しい
    ● まだ未解決

    View Slide

  69. 運用した結果 変更
    ● 計測ツール: Instruments CLI
    ● 最新 アプリ: Bitriseでビルド
    ● 実機: HeadSpin(端末数が増えた)
    ● CI(計測): Jenkins
    ● アプリ操作用 UITestフレームワーク: XCUITest
    ● 負荷をかけるツール: お手製
    そ 他細かいところ 調整している

    View Slide

  70. これから 展望

    View Slide

  71. xctrace
    Xcode12からInstrumentsコマンドがdeprecatedとなりxctraceが追加された
    ● 基本的にInstrumentsコマンドでできていたこと できる
    ● traceファイルからXML形式でデータが取得可能
    ● Thermal stateが取得できること 確認済み
    ● CPU使用率について 現時点で 難しいかもしれない

    View Slide

  72. Bitrise(MacStadium)へ 移行
    当初2時間で 計測も考えていたが、今 30分 計測 みに変わった
    ● 結果として90分制限に縛られなくなったためBitriseへ 移行も考えている
    ● Instrumentsで 計測にそれなり スペックがないと不安定な でそこだけ心配
    一方でJenkinsもオンプレからMacStadiumへ移行している
    ● Mac miniを借りれるクラウド
    ● MacStadiumだと再起動が出社なしで可能

    View Slide

  73. 他項目 計測
    今計測している項目以外でも計測したいも が出てきている
    そ ため現在、FPSなど 新たな項目で 計測 準備をしている
    そちら Big Queryにデータを入れてData studio等で可視化を検討している
    こ パフォーマンス計測もそこに合わせてデータを可視化したい

    View Slide

  74. さいごに
    今回紹介した計測方法 あくまでも一例
    アプリ 特性や何を計測したいかでも変わってくる
    アプリ 特性にもよるが、パフォーマンスがまだ問題になっていない であれ
    MetricKitから導入してみる がいいかもしれない
    そこから改善 サイクルを回していきましょう

    View Slide

  75. DeNA Tech Twitter アカウントで 、
    DeNA エンジニアリングに関する
    登壇資料やブログを紹介しています!
    後日ブログで紹介しきれなかったところを書く
    でそ 告知もあります

    View Slide

  76. ありがとうございました!

    View Slide