View in English

  • Apple Developer
    • 今すぐ始める

    「今すぐ始める」を詳しく見る

    • 概要
    • 学ぶ
    • Apple Developer Program

    最新情報

    • 最新ニュース
    • Hello Developer
    • プラットフォーム

    プラットフォームを詳しく見る

    • Appleプラットフォーム
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    特集

    • デザイン
    • 配信
    • ゲーム
    • アクセサリ
    • Web
    • Home
    • CarPlay
    • テクノロジー

    テクノロジーを詳しく見る

    • 概要
    • Xcode
    • Swift
    • SwiftUI

    特集

    • アクセシビリティ
    • App Intent
    • Apple Intelligence
    • ゲーム
    • 機械学習とAI
    • セキュリティ
    • Xcode Cloud
    • コミュニティ

    コミュニティを詳しく見る

    • 概要
    • 「Appleに相談」イベント
    • コミュニティによるイベント
    • デベロッパフォーラム
    • オープンソース

    特集

    • WWDC
    • Swift Student Challenge
    • デベロッパストーリー
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Center
    • ドキュメント

    ドキュメントを詳しく見る

    • ドキュメントライブラリ
    • テクノロジー概要
    • サンプルコード
    • ヒューマンインターフェイスガイドライン
    • ビデオ

    リリースノート

    • 注目のアップデート
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • ダウンロード

    ダウンロードを詳しく見る

    • すべてのダウンロード
    • オペレーティングシステム
    • アプリ
    • デザインリソース

    特集

    • Xcode
    • TestFlight
    • フォント
    • SF Symbols
    • Icon Composer
    • サポート

    サポートを詳しく見る

    • 概要
    • ヘルプガイド
    • デベロッパフォーラム
    • フィードバックアシスタント
    • お問い合わせ

    特集

    • アカウントヘルプ
    • App Reviewガイドライン
    • App Store Connectヘルプ
    • 近日導入予定の要件
    • 契約およびガイドライン
    • システムステータス
  • クイックリンク

    • イベント
    • ニュース
    • Forum
    • サンプルコード
    • ビデオ
 

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • すべてのビデオ
  • 利用方法

その他のビデオ

  • 概要
  • トランスクリプト
  • Appのパフォーマンスを向上させるための実践的なアプローチ

    パフォーマンスや全体的な反応を向上させることは、すべてのAppで行うべきことです。このセッションでは、Instrumentsやその他のツールを活用し、パフォーマンス上の問題を解決する方法について詳しく紹介します。さらに、XcodeやiOSの写真Appなど、Apple自身のAppのパフォーマンスを調整した経験に基づく、実践的なアドバイスも紹介します。

    リソース

      • HDビデオ
      • SDビデオ
    • プレゼンテーションスライド(PDF)

    関連ビデオ

    WWDC20

    • スケーラブルなエンタープライズAppスイートのビルド

    WWDC18

    • テストのヒントとコツ
    • Measuring Performance Using Logging

    WWDC16

    • System Trace in Depth
  • このビデオを検索

    (音楽)

    (拍手) こんにちは ジョン・ヘスです Practical Approaches to Great App Performanceの話をします 私は Xcodeチームのエンジニアとして この数年 パフォーマンスの問題に 取り組んできました まず Project Findと Open Quickly パフォーマンスを左右する 主要な機能となる2つの領域です 最近 XcodeのGUIの応答性について 調査する機会がありました そこでのアプローチを 共有したいと考えています 私が熟知しているコードと 初めて経験したコードの 両方で行いました

    今日のセッションで 最も大切な教訓を1つ教えます “測定こそが パフォーマンスの基盤となる” パフォーマンスの問題を 解決したければ まず 測定して現状を知ることです 修正を繰り返し行う場合― 期待どおりの効果が出ているか 毎回測定する必要があります 問題が解決したら 再度測定を行います 最初の段階と比較して― パフォーマンスの改善状況を 定量化します それを上司や同僚やユーザと 共有するのです

    ユーザ向けに パフォーマンス改善を行う場合― “トータルパフォーマンス インパクト”が大切です 例えば アプリケーションの 1つの分野の機能と性能を― 50パーセント改善します でも ユーザの1パーセントしか 使わない機能だったら? すべてのユーザがよく使う機能を 10パーセント改善する方が 大きなインパクトがあります エッジケースの最適化ではなく― トータルなインパクトを 重視してください

    性能のバグをどう解決しますか? 通常のバグの場合― ユーザからの不具合報告で 始まります アプリケーションの不具合状況が 記されています 問題のある動作を 再現する方法を見つけ― わざと不具合を起こします そこで デバッガに接続すれば― 不具合の内容が確認できます

    そこで コードの本来の動きと 組み合わせて 必要な修正と 不審な動きの排除を行います 何か副作用が 起きていないか確認して バグが完全になくなるまで 検証を続けます

    性能のバグもこれと同様です 唯一違うのは デバッガではなく― 測定に適したツール “プロファイラ”を使用します プログラムの動作が遅いのを 再現する方法を見つけます プロファイラを用いて そのステップを走らせると 動作が遅い時の コードの動きが分かります その知識と― その時 プログラムが 行うべき動作を統合します そして 問題となっている ステップを排除します 基本的に― ムダなステップを取り除くと コードが高速化します どんな場合でも同じです

    コードを修正して― 期待した結果が出るまで 修正と測定を繰り返します

    このような作業をする際― いくつかの状況に遭遇します 状況によって バグを再現させるための コードのテスト方法も異なります 時々起こるのが 性能のリグレッションです 順調に動作していたのが 誰かがチェックすると 性能がひどく落ち込んでいます その原因を 突き止めなければなりません リグレッションが明白な場合 あるいは 近い将来に 再現しないと考えた場合 プロファイラを用いたテストで 終わらせるかもしれません でも パフォーマンスの“勝利”は 簡単にはつかめません 緩やかなリグレッションを 見つけるのは困難です 皆さんにお勧めするのが― 自動化された性能テストを 使うことです アプリケーションの性能を 把握することで 緩やかなリグレッションに 気付くことができます

    もう1つの状況です アプリケーションの動作が ずっと同じ場合です 例えば 描画テストで 45fpsで動いていて 60fpsが目標だとします わずかに改善する必要がありますが 部分的な修正で解決できると 分かっているケースです この状況でも 自動化された 性能テストが有効です これまでの経験から言えます

    3番目の状況です 設計不良により アプリケーションの性能が 目標より大きく低下しています 部分的な修正では改善できません 過去に何度か修正しましたが まだ性能が劣っています この場合は 徹底的な修正が必要です 機能のコア部分や アルゴリズムの再設計を行います 性能に大きな影響を与えるからです このような場合は 性能テストを行い― 問題が解決したか 測定する必要があります 何をテストすべきでしょう このような修正を行う時は “一気にすべてを進めない” これが大切です 本当はそうしたいのです 何もないところから すべてを組み立てる でも それは危険です 改善を成し遂げたくても すべての機能を手直しするのは 苦難の道です

    この時 理解すべきなのは― コードの機能的な制約だけでは ありません 性能面における制約 そして 多くのユーザに当てはまる 典型的な使用パターンも含まれます 過去に実施した検証が それを可能にします 私が Xcodeで経験した状況を 共有しましょう Xcode 9で Project Findの 修正を行いました 目標は数十ミリ秒で 検索結果を表示することです それについて同僚と議論した時― 大きなプロジェクトをまたぐ検索が 課題でした 例えば 文字列や“E”を含む文字は 膨大な結果が出ます アプリケーションが 検索結果を即座に出せたら かなり高速です しかし 通常はどうでしょう 使用しているAPIや クラスの名前を探します または 参照している画像の名前 たぶん数十か数百の結果を出します もちろん 100万件の検索結果が 必要な時もあります しかし 通常は数百件です 検索で行うことのいくつかは 生の検索結果を出すことです 他には 効率的に テキストにインデックスを付けて 最初の作業を省くことです これら2つの状況は 目的がまったく異なるので どちらを優先するかで 最適化の方法が異なります ですから大切なのは― ユーザの目的を理解して それに合った最適化を行うことです

    テストには 手作業か自動かに関わらず― ある種のフォームが必要です

    2つの性能テストを紹介します Xcodeの性能を測る 典型的なものです

    ユニットテストと― インテグレーションテスト 2つを比較します まず ユニットテストです アプリケーションの 一部の機能を分離して 性能を自動測定します 依存を遮断して― 他の機能と切り離して テストを実施します 私が Xcodeのコード補完のための テストを行うなら 3つのテストを1セットにします まず1つ目 コンパイラを使って 生データの結果を得て― コード補完の候補を返します そして2つ目 結果の相関性 序列 スコアを 測定し― どれを表示するか判断します 3つ目は それらの結果をもとに 画面のUI要素に入れていきます この3つのテストにより― 開発環境に必要な コード補完の要素をカバーできます

    ユニットテストには いくつかのメリットがあります リグレッションに 重点が置かれているので 問題が起きた時 場所の特定が容易です コードがすでに調査済みだからです

    さらに 再現性の高い結果を 生成します 実施ごとに 大きなばらつきもありません コードは明確です 次に インテグレーションテスト ここでは ユーザと同じ状況で― アプリケーションの性能を 測定します 全体的にです インテグレーションテストで コード補完を書いているとします Xcodeのアプリケーションを すべて立ち上げ― ソースファイルを開きます ファイルを操作し タイプして― コード補完を何度も繰り返します この時 Xcodeが何をやっているか 監視すると― 他には何も行っていません 私のタイプどおりに 描画し配置して― シンタックスカラーリングを しているのです 裏ではインデックスを作成し ステータスを取得して Assistant Editorに 表示するファイルを決めています これらのすべては コード補完と連動して CPUのリソースで競合しています プロファイラでは 80パーセントを シンタックスカラーリング 20パーセントをコード補完に 費やしているのが分かります コード補完の性能を改善する― ベストな方法が見つかりました シンタックスカラーリングの 先送りです これはユニットテストでは 得られなかった知識です 今日 皆さんに2つの教訓を 与えられるなら― 2つ目は以下です “性能の検証は―” “インテグレーションテストから 始める” そこでユーザ体験を測定します

    テストと測定について 説明してきましたが― 今からツールを使った プロファイリングの紹介をします デモ機を使用します

    パフォーマンスに問題があり― Xcode 9とXcode 10の間で 修正を行いました それをお見せします Xcode 9を立ち上げ― アプリケーションのソースを 開きます

    これから見るのは タブ作成の問題です “command + T”を数回押します この時 画面が黒く点滅して タブを作成するのに 数秒かかります 明らかに期待していない動作です 修正の必要があります その方法をご覧ください

    Instrumentsを立ち上げます プロファイリングのツールです メニューのXcodeから開けます “Open Developer Tool”の下の “Instruments”です これは Xcode 9なので そこから“Instruments”が 立ち上がります でも今回は 私の“Dock”にある― Xcode 10用を使います Xcodeを隠して持ってきます

    Instrumentsが 立ち上がりました 測定に使う プロファイリングツールの一覧です さまざまな測定が可能です グラフィックスの使用率 メモリ消費量 I/O さまざまな時間

    どれから使えばいいのか 戸惑うかもしれません

    お勧めがあります この中の1つを学ぶなら― Time Profilerです 私は測定の95パーセント以上を これで行っています アプリケーションが遅いという 問題は― 処理時間が長すぎるのが原因です I/Oが多すぎて遅いのならば― 時間に関係するので Time Profilerで検証できます 1つだけ選ぶならば Time Profilerです 使い方を見ましょう

    ダブルクリックするだけで 立ち上がります

    “Instruments”を 全画面にします

    ここでXcodeを記録します 左上の “Instruments”ウインドウで 記録プロセスを コントロールできます デフォルトでは この“記録”ボタンを押すと すべてのプロセスが “My Mac”に記録されます 今回は Xcodeに絞ります

    ターゲットを Xcodeに切り替えて― “記録”を押します ウインドウのこの部分に注目して トラックしたいと思います ウインドウを少し小さくします まだ見えますね 先ほど問題のあった タブをいくつか作成します

    ここのグラフが変わりました ここで停止して― Instrumentsに戻ります

    何が起きたでしょう? プロファイラが走っている間― デバッガのように プロセスを追跡していました 毎秒数千回 止まっています それが止まるたびに バックトレースを収集します 念のため言いますが バックトレースはプログラムが たどった経路を記述しています 例えば functionCの 6行目にいるなら― メインがAを呼び Bを呼び そしてCを呼んだからです そして 経路は “メイン A B C”となります Instrumentsが その1つを選んでこう記述します “functionCで1ミリ秒費やした” それがサンプリングの間隔で ミリ秒ごとに記録するからです

    メインスレッドでは― すべてのバックトレースが main functionから始まります application mainを呼んで 枝分かれして すべてのコードに広がっていきます これらのバックトレースを 折り畳み― プレフィックス木を展開します メインから広がっていくのです ミリ秒ごとのカウンターを 最上位で集めるので ソースコード各領域の所要時間を 階層的に見られます これにより 冗長で不必要な オペレーションを見つけ― 高速化を図れます アプリケーションの性能を 向上させる基本手段です ご想像のとおり― 毎秒数千回のバックトレースです Instrumentsには 膨大なデータがあります 最も重要なのは― データをできるだけ フィルタリングすることです そうすれば 道筋が見えてきます 細かい点にとらわれてはいけません ここで 強力なフィルタの 使い方をご紹介します

    先ほどトラックビューを 見えるようにしました

    新しいタブを作っている間に CPUの使用率が― どこでどのように変化するか 確認したかったからです この部分だと分かりました ドラッグして そのトレースのエリアを選択し― “Instruments”に フォーカスさせました その間の経路だけに 焦点を当てます この部分はタブを作る前です こちらがタブを作った後で― アプリケーションを止めた時です 最適化する部分ではないので このデータは見ません

    さて―

    “Instruments”ウインドウの下に すべてのトレースデータがあります デフォルトでは スレッドごとに 一列に表示されています この例で走っているスレッドは 4つです これは同時に走る アプリケーションの数で異なります 私はこれらを集約するために 折り畳みます また 各スレッドを― スレッドIDではなく 上位の機能に基づいて折り畳みます これでGrand Central Dispatchが 使いやすくなります “Instruments”ウインドウの 下にある― 呼び出し木のボタンを クリックします よく分かるようにズームします いくつかのフィルタがあります これはスレッド別で デフォルトは“オン”です これを無効にして― スレッドをIDではなく 上位機能別にグループ化します

    このトレースを見てください 動作中のスレッドが確認できます メイントレースの下が CPU使用量の合計で― スレッドごとの CPU使用量が分かります このトレースの間 他のスレッドは ほとんど動いていません ここでメインスレッドだけを 選択して― この間のメインスレッドだけを トレースします

    このコールの階層を掘り下げて アプリケーションの動きを 確認します 通常 キーボードを使う時は― 右と下の矢印で操作します でも今回は Instrumentsが提供する― 高度なインスペクタを紹介します インスペクタが見えなければ このボタンで切り替えてください この“Extended Detail”のタブで 高度なトレースが可能です ここでトレースするのは 最も頻繁に現れた経路です 現在の選択範囲の中で― 最も頻繁にたどった経路です ここで一度に 多くのフレームを操作できます 通常 自分のAPIを探す時に ここを見ます 驚くほど時間が かかっている場所 または 多くの分岐点がある場所を 探します ここにある“IDE Navigator”の コールを見ましょう ビューコントローラを インストールしてあります これは 私が熟知している Xcodeの内部APIです このトレースの 左端の部分を見ると 1.19秒で返していることが 分かります 記録した時間の 45パーセントを占めています これは 私の予想を はるかに上回る時間です

    その要因を知るのは困難です この下にすべての経路が 出ていますが スタックの深さが 30から40はありそうです ここでどう絞り込むか 見せましょう 最初のやり方は 呼び出し木に戻ります

    このポップオーバーを使って “Flattened Recursion”を 選択します やってみます

    ここにメソッド呼び出しの 繰り返しが見えます 畳み込んでしまいました

    スクロールします

    この部分を見てください 実は IDE Navigator内部の API呼び出しに― 問題の要因があると 確信しています 呼び出し木全体を 再度フォーカスします ここをクリックして― “Focus on Subtree”を 選択します “Instruments”が コールグラフのトップに移動して すべて削除します パーセンテージを 100パーセントに再設定するので ここにフォーカスできます 検証を続けましょう この矢印キーで操作できます 私はこのAPIを熟知しています ここでは 復元作業をしているようです さらに展開します テーブルビューの奥深くです ここでは 最新のコールパスが 全体の大きな割合を占めています さらに付随するサンプルもあります

    ここにすべて集約されています その1つが objc messageSendです これは Objective-Cで 書いていると起こります Swiftコードでも― システムライブラリを使っていると これが起こります 対応する機能も目にします “objc”や“load strong” “load weak”や“retain”など これらを呼び出し木から すべて取り除くことができます

    コンテキストをクリックして 以下を選択します

    “Charge libobjc.A.dylib to callers” “libobjc”からのサンプルを すべて拾い取り除くよう― Instrumentsに命令しています しかし 親フレームが呼んだ時間は 保持したままです 私はこれらの実行時間を― Objective-Cを書く時に 必要なものと捉えています それを最適化することは ほとんどないので データから取り除いて 必要な部分にフォーカスしています フィルタの適用方法を もう1つ紹介します それが このセットフレーム間に 生じた― 細かいサンプルの削除です “Call Tree Constraints”の中に あります

    見てください

    Instrumentsにこう言います “トレースの中の20ミリ秒以上の サンプルが見たい” すでに2秒間隔は選んだので 20ミリ秒にしました それは全体の 約1パーセントに当たり― 必要な精度に合致しています

    Call Tree Constraintsを 呼んで― “最低20”と設定します この部分をさらにフォーカスします ビューアイテムを展開しています 実際には NSOutlineViewを呼んで― アイテムと子を増やしています 多くの人がコールグラフで 立ち止まるかもしれません システムフレームワークに 多くの時間がかかると 思っています どうしたらよいでしょう? NSOutlineViewは 最適化できません この状況の打開策があります システムフレームワークに 時間がかかる理由 それは データ作業を 行っているためです このメソッドを 何千や何百万回も呼んでいます あるいは コードを 呼び戻しているかもしれません 重要なのは― フレームワークの動きを 読むことです Instrumentsの階層を 展開することで 呼び出している機能が分かるのです これこそバグ修正の方法です

    トレースをアウトラインビューに 展開すると― 2つのメソッドを呼んでいるのが 分かります

    “Batch expand items with item entries expand children” “Do work after end updates” これらをまとめることで 効率アップが実現しそうです ご想像のとおり アウトラインビューは― 一式のアイテムからスタートします そして コードの領域で 展開を復元しようとします 例えば 一番上のアイテムを開きます その指示を出した時― 内部では 他のアイテムを下げているのです 2番目のアイテムを開く時は― すべてを再度下げています 3番目も同じです それを行うごとに― アイテムを何千回も 動かしているのです パフォーマンスの改善をする上で まさに取り除きたい― ムダな作業です これらのメソッド呼び出しが バッチを実行している事実から― こう考えました “アウトラインビューに大量の 作業を要求できるAPIがある” コールを呼び出すと― それがすべての配置を 1度で計算するのです このようなコールもあります “更新完了後に作業する” 時々 APIが配列計算する 大量のメソッドを処理します また別の時には トランザクションのAPIを提供し 変更を加えようとします そして それが終わったと伝えると その変更に対して発生した すべての計算を行います すべて1つ1つやるより 効率的です ここで NSOutlineViewや NSTableView APIに進み― いくつかのメソッドを探します NSTableViewには― 開始と更新の完了のための 複数のメソッドがあります これはテーブルビューを統合し 作業を効率化します Xcode 10に搭載しています お見せしましょう

    Xcode 10を起動します

    アプリケーションとして ソースを開きます

    タブを作成します 先ほどのような点滅はなく― タブがすぐに開きます さて―

    もっと早く開きたいと思います どうしたらよいでしょう? 幸運にもトレースを検証していて サンプルの半分を占める― 明らかな問題を見つけることが できました

    こんな大きな手掛かりは めったに見つかりません 通常しなければならないことは フィルタを使った サンプル全体の調査です そして全体の1パーセントの 処理について調べます そうやって 1つ1つの原因を探して― ほんの少し速くする解決法を 見つけるのです

    それを紙切れか テキストに書き出して― 解決する順番を決めていきます 時々 5番目の修正が― 2番目の問題に 役立つこともあります 余計な仕事をして 作業の順番を変えるのは 本末転倒で気分が悪いものです しかし すべてを予測するのは困難です 作業が終わるまで分かりません まず始めてみることです 3パーセントの改善を 10回積み重ねることが 2番目の30パーセントの改善に つながります

    いいですね? では スライドに戻ります 継続的な改善に役立つ テクニックを紹介します

    最も頻繁に起こる問題は― アウトラインビューと 同じテクニックを使っています “バッチ”と“延期”です APIが呼ばれた時に 副作用が起こると― APIをループする コードを受け取ります 要求された最初の命令を実行して 副作用が起こったのです 副作用の結果を 誰も理解していなければ その仕事を何度も繰り返します もっと効率的なインターフェイスを 得られます クライアントが提供する 配列やコレクションの― バッチインターフェイスを 使用するのです それで副作用の計算が 1度で完了します クライアントが 複数の場合もあります 一括にまとめることができず 作業を延期しているため まだ 性能が同じ状態です

    3つ目はInstrumentsの トレースを調べて― 同じ計算を何度もしている領域を 見つけることです 例えば テキストサイズを計算する メソッドがあります そして その数フレーム後― 同じ計算を何度もしている部分が あったとします このような場合は 1回で計算したいはずです 最上位で計算し 下位に渡すかキャッシュします

    UIアプリケーションにおける もう1つのテクニックは UI表示に使用するビュー数を 考えることです ビュー数が少ないことは ソースコードの構造において 大変有効です 小さな機能のセットを 大きな塊に組み立てるのです ビューが増えると― 表示やレイアウトのシステムへの 負担がその分重くなります 双方向の関係性です ビューが少なければ より細かいキャッシュが得られ― パフォーマンスも向上します 通常はビューの数を調整できます パフォーマンスに 大きな影響を与えるためです ビューが少ないことが 常にベストではありません さもないと 巨大なビュー1つで すべてをやることになります

    もう1つ よく使うテクニックに “ダイレクトオブザベーション”が あります ソースコードの2つの領域が 緩やかに連動していることが よくあります 一方が他方を分かっていて― 間接的な方法によって 互いに交信しているのです 使用しているのは NSNotificationCenter あとは ブロック単位の コールバック “委譲”や“キー値監視”です

    いくつかのモデルコードを 目にすることがあります ループに入って変更されるたびに そのループに入っていき― “KVO Notifications”を 数多く出しています もちろん直接は見えません しかし コントローラの中では モデルコードの変更に 必死に応答しているのです これに CPUが多くの時間を 費やしていて 変更全体で考えた時に 不要な処理となっているのです これが モデルコードからの 呼び出しだったら? 通知や委譲を経由していたり― 手動のブロックベース コールバックだったら? 何が起こっているかが ずっと明らかです そして適切な処理をするでしょう いくつかの通知を ループの中から外に出して― パフォーマンス向上を図るのです コントローラサイドの やり方もあります ここでは 延期とバッチの テクニックを使って ムダな仕事を省いて 同期応答を回避できます

    最後は簡単です コードが すでに適切に動いていれば― すでにリニアということで 理想的です ある意味 パフォーマンスの 向上の余地も限られます その場合は 定期的な改善を続けることです オブジェクト指向の ディクショナリを使っているなら お気付きでしょう すべてのキーに 大量の文字列定数があるなら 大きな改善が可能です コードの明瞭化や補完 リファクタリング 特定の型を使った ソースコードの検証 structを使うのが 一番簡単でしょう 暗黙のイニシャライザや ハッシュ値との適合も使えます これでソースコードが改善します 文字列ハッシュや文字列方程式に 費やしていた時間に― 驚くことでしょう すべては 小さな改善の積み重ねです 次はマシューに引き継ぎます これらのテクニックの― 写真 Appへの 適用方法を紹介します

    (拍手) ありがとう こんにちは 私はマシュー・ルーカス 写真チームのエンジニアです 今日は 写真 Appの パフォーマンスに関する― 実例をいくつか紹介します まず 写真 Appについて 少し話します よくご存知の アプリケーションですね お気に入りの瞬間を 保存して閲覧できます この“モーメント”から閲覧します 今見ているのがデフォルトです それ以外に“コレクション” “年別”の表示もあります 後ほど説明します ライブラリには 1000枚から 10万枚の写真が保存できます どれほど写真が好きかで変わります 私たちは毎日の楽しい瞬間を 記録するのが大好きです 記録することには寛容な一方― こんな画面は我慢できません アプリケーションを起動して― このような画面が出たら どう思いますか? このような画面を 目にすることもあるでしょう 多数のプレースホルダが 表示されていますが― 問題があります スクロールしていると このようにグレーになり― サムネイルがロードを始めます スクロールを続けると フレーム落ちしてしまいます ビューが更新されているからです 目標はこのような表示を なくすことです 望ましいユーザ体験ではありません 避けられない場合もありますが 頻繁に起こるのは困ります

    アプリケーションにとって 反応の速さは重要です アニメーションが スムーズなことも大切です

    この2つは ユーザ体験の基本です ユーザがアプリケーションに 信頼が持てなければ 使用をやめるかもしれません この2つ問題について 2つの事例をご紹介します 最初が モーメントを 立ち上げる時の最適化 次が コレクションと年別の スクロールを― スムーズにする方法です

    最初に モーメントを起動します

    起動には3種類あります 最も時間がかかるのが “コールド”と呼ばれるもの リブート後にアプリケーションを 再起動させます キャッシュに 何も保存されていません そのため バックグラウンドで プロセスが走ったり― ライブラリのロードが 必要かもしれません また システムがメモリ不足で メモリの再要求をしている時にも 起こります

    アプリケーションを中止しても コールドにはなりません リソースがページアウトされる時を システムが決めるからです

    アプリケーションを中止して 数秒後に再度立ち上げると 問題なく速やかに起動します これが“ウォーム”です リソースが すでにキャッシュに 保存されているので 早く立ち上がります

    最後が“ホット”と 呼ばれるもので― 基本的にレジュームを指します 起動しているアプリケーションを 復帰させる状態です

    起動の評価をする場合は ウォームから始めます ウォームからの起動時間は コールドに比べて― 変動が少なくなります デバイスのリブートが不要で テストのイテレーションも高速です 起動の評価はアプリケーションの アイコンを押してから やりとりを始めるまでの 所要時間を測定します ここで言う“やりとり”は 実際にアプリケーションを 使い始めることです

    通常 立ち上がってすぐは スピナーが表示され― アプリケーションが使えないので その時間は省きます

    ここでは3つの目標があります 最初の目標は“瞬時”です スピナーやプレースホルダも 表示したくありません

    灰色のサムネイルも同様です 正直に言うと― 初めて iCloudに同期する時は プレースホルダが現れます でも データがローカルにある時は 表示しないようにしています

    さて“瞬時”とは何でしょう? 起動までの時間は― ズームアニメーションの表示と 同時でなくてはいけません 通常 500から600ミリ秒の間です それならホーム画面から アプリケーションへの移行が円滑で アニメーションが終わり次第 使い始めることができます これは写真 Appに限らず― どんなアプリケーションでも 有効です

    次に 写真 Appの起動方法です より詳しく見ると アニメーションが終わる前に 写真がすべて配置されるのが 分かります

    起動分析を見ると― 大きく2つのパートに分かれます 最初のパートは“dyld”です 必要なすべてのライブラリの 読み込みをするローダで staticイニシャライザも作動します このパートの制御は限定的ですが 不可能ではありません 詳しくは 昨年のdyldに関する セッションをご覧ください

    理解を深めるのに役立ちます

    dyldはオブジェクトテーブルの mainを呼び出し― 多くの制御が可能な 2番目のパートに移ります このパートは 500ミリ秒未満となります “didFinishLaunching”のあとの “First layout”が 起動終了のサインになります これがアプリケーションが使える 時間です

    このセッションで伝えたい いくつかの原則があります それらは パフォーマンス改善の 共通の柱となります 1つ目は“怠け者”になる 必要のない仕事は延期します 2番目は“先回り”する これは2つの意味で有効です まずは “後回しする作業を予測する” 次に“リグレッションを いち早く見つける” インテグレーションテストの 継続的な実施が重要です

    最後は“一定” ロードするデータ量に 関わらずです

    アプローチ方法を間違えて― 起動に必要な すべてをロードするとします それは 3万アイテムにも 及ぶことになります

    まず データベースを初期化して ビューコントローラを用意します そして データソースを構成し― ライブラリ画像をロードして クラウドのステータスを定義します

    これはデータの増え方によって 変わります ユーザは日々写真を撮っているので データは永遠に増え続けます 私たちが扱っている写真は 結び付きのないデータの塊です

    次に各ステップを 最適化する方法を紹介し― データベースを初期設定します

    通常 最初のクエリが 要求された時に― データベースが 初期化されてロードされます バックグラウンドスレッドでは 即座に最適化が行われます そのため クエリの要求が完了した時― 初期化は必要ありません これは 最初のクエリが― メインスレッドから 行われた場合のことです

    私たちは 多くの時間を費やして― 起動の時に すべてのクエリを見ています 今している作業が必要なことか ムダがないか確認してください

    最後に確認したいのは すべてのクエリが 最大限に効率化されているか そして 複雑なクエリが 極力回避されているかです

    有効な方法として インデックスを作成し― スピードアップを 図ることができます

    これで初期設定の時間は 最大30ミリ秒に短縮できます 次に ビューコントローラの 起動設定に移ります 主要な機能として 4つのタブがあります 最初に注意すべき点です これら3つの不可視ビューに おいて― 初期設定時の作業を 最小限にしたいです ここでのルールは― イニシャライザの作業を 最小化することです 必要最小限にした上で ビューの全データを記録します

    さらに コントローラの初期化も 一定時間の中で行います

    最後に可視ビューだけが ロードされたことを確認します この部分で 退行することがよくあるので 十分な注意が必要です

    ビューコントローラの起動目標は 120ミリ秒です しかし ここで データソースの設計を行うので そのチャンクを見ていきます

    モーメントには 人生の出来事が記録されています UIはそれをグループに分類して 表示しています 例えば このライブラリには 500モーメントくらいあり― ビューを作成するため 事前にそれらの読み込みが必要です

    モーメントに本当に必要なのは ビューを作成するための メタデータだけです コンテンツは不要です そこで最初に行うのは 超高速なクエリを投げることです 次に 必要なコンテンツだけを 読み込みます この場合 可視コンテンツだけを ロードします このケースでは 7から10までのモーメントです

    不足分は限られているので― メインスレッドで 同期することができます

    さらに 残りのデータを 同期してロードできるように 作業の予測と計画を 立てたいと思います バックグラウンドスレッドで 行い― メインスレッドの動作に 影響を与えないようにします

    ここでの目標は100ミリ秒です

    そして 最後に― データソースが画像を提供します このパートを最適化しましょう

    ここは飛びぬけて 大きなチャンクだったので 画像のロードに 多くの時間を要していました ここでの作業が多すぎるようです まず最初に― 起動時に必要な 画像数の検討を行います そして それだけを 最初にロードします

    この場合 最大60枚くらいになりそうです

    次に それらを 最初にロードするため― 低解像度の画像だけ 読み込む必要があります ピクセル数が小さい画像の方が ずっと効率的です

    今 このチャンクは 200ミリ秒になっています

    以前に比べると大きな進歩です この時間を維持できれば すばらしいことです

    時々 こう自問自答してください “これは起動時に必要なことか?” ここで挙げる例はフッタビューです ネットワークやデータベースから 情報を引き出し―

    起動時にデザインを 表示しないようにします 可能な限り表示しようとした 画像の優先順位を決めるためです これで単純化されます 起動後の作業予定を立て― あとで呼び出すプロセス情報を キャッシュに格納します

    この情報の表示要求を 受け取っていたとしたら? Background App Refresh APIを UIKitから利用できるでしょう アプリケーションがクリアされて 起動時に コンテンツを 立ち上げることができます

    その部分が消えて CPUの時間が 400ミリ秒節約できました この内訳を見ると― ここまで 450ミリ秒しか 使ってないことが分かります

    これを 500ミリ秒の タイムウインドウに収めていきます ここでは 表示の仕方に関わらず― コンテンツの準備時間を 考えることが最も重要です つまり それを測定することです

    ロードするデータ量に関係なく― 一定時間で 処理しなければなりません 関連性のないデータですが 一定を保つ必要があります

    アプリケーションを立ち上げて 使い始めます コレクションと年別の 整理方法を紹介します

    ユーザはモーメントから コレクション 年別まで アニメーションで シームレスに移動できます

    これは複雑な階層です 写真が何千枚も表示されています この階層を行き来しながら― 最新更新やアニメーション ジェスチャまでサポートします

    ここでも目標があります ユーザ体験に関する目標です 1つ目は前と同じで― “スピナーやプレースホルダを 表示しない” さらに “スムーズなアニメーション” ここで言う“スムーズ”とは― スクリーンに応じて 60fpsや120fpsを指します

    先ほどの原則が ここでも当てはまります “怠け者”になって 必要のない仕事は延期する “先回り”して リグレッションを早く見つける そして レイアウトパスで “一定”を保つ ロードするデータ量に 関わらずです

    ここでは“タイムリー”な― レンダリングの ループサイクルも大切です 忘れないでください フレームの描画時間は 8か16ミリ秒しかありません そのタイミングを逃したら フレーム落ちしてしまうのです

    ここで達成したいことを 見ていきましょう セクションの中に小さなセルのある このビューを見てください

    “UICollectionView”の画面です 極端な例を除いて― 通常のアプローチで 可能な限度を制限しています ビューとレイヤが 増えすぎたからです

    さらにレイヤの複雑性が増し― 多くのメモリが必要になりました

    イノベーションが必要でした そこで コレクションビューを 使いながら― ビューの数を 制限することにしました

    ビデオゲームでよく使われる “atlasing”を使いました 簡単に言うと 画像一式を 1つに結合するテクニックです まず 小さなサムネイルで それを効率的に使い― 次に デザインカンバスに― すべてのRaw画像データを スタンプします

    Raw画像データを使用しているので それぞれのサムネイルの デコードを省けます

    基本的にランダムな画像列を 表示しています

    生成とキャッシュが オンザフライなので― より柔軟です

    複数の画像を 1つにまとめて表示するので セル レイヤ オブジェクトの数が 大幅に減ります レイアウトが簡素化され 時間も短縮します

    それと交換に 考えるべきことがあります これがその1つです

    ここにある画像を“長押し”や “早押し”した場合― その場所を特定して 正確に表示する必要があります

    そのため 1つの画像を表示する時ー 個々の画像と表示列の位置を 維持する必要があります これらをオンザフライで 生成するのはなぜでしょう?

    最新情報を サポートするためです 多様なビューサイズの サポートも必要です これは横長です こちらは縦長です これには他にも理由があります ライブラリの画像は 有機的に増えていくものなので 数千のライブラリを作成するのは 非常にまれだからです

    セクション全体を 生成しないのはなぜでしょう?

    このアニメーションを行うためです コレクションが セクションに展開したり― 逆にグループに 折り畳まれたりします

    2番目のパートで もう1つ大切なこと それはビュー階層の レイアウトコストを考え― それを測定することです

    最後は 常にパフォーマンスを 考えること 私たちは日々 そのことを考え改善を重ねています

    より詳しい情報は― ここに映っている 3つのラボで紹介します 引き続き WWDCをお楽しみください ありがとう (拍手)

Developer Footer

  • ビデオ
  • WWDC18
  • Appのパフォーマンスを向上させるための実践的なアプローチ
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • Apple Intelligence
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習とAI
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • Mini Apps Partner Program
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    最新ニュースを読む。
    Apple Developerアプリを入手する。
    Copyright © 2026 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン