プロファイラ API

Profiler を使って、React アプリケーションのレンダーの頻度やレンダーの「コスト」を計測することができます。 本機能の目的は、アプリケーション中の、低速でメモ化などの最適化が有効な可能性のある部位を特定する手助けをすることです。

補足:

プロファイリングには追加のオーバーヘッドが生じますので、本番ビルドでは無効化されます

本番環境でプロファイリングを利用するために、React はプロファイリングを有効化した特別な本番用ビルドを提供しています。 このビルドの使用方法については fb.me/react-profiling をご覧ください。

使用法

Profiler は React ツリー内の特定部位におけるレンダーのコストを計測するため、ツリー内のどこにでも追加できます。 2 つの props が必要です。id(文字列)と、ツリー内のコンポーネントが更新を「コミット」した際に React が毎回呼び出す onRender コールバック(関数)です。

例えば、Navigation コンポーネントとその子孫のプロファイリングを行うには:

render(
  <App>
    <Profiler id="Navigation" onRender={callback}>      <Navigation {...props} />
    </Profiler>
    <Main {...props} />
  </App>
);

アプリケーション内の複数部位の計測を行うために複数の Profiler コンポーネントを使うことができます:

render(
  <App>
    <Profiler id="Navigation" onRender={callback}>      <Navigation {...props} />
    </Profiler>
    <Profiler id="Main" onRender={callback}>      <Main {...props} />
    </Profiler>
  </App>
);

同一のサブツリー内の複数のコンポーネントで計測を行うために Profiler コンポーネントをネストすることもできます:

render(
  <App>    <Profiler id="Panel" onRender={callback}>
      <Panel {...props}>
        <Profiler id="Content" onRender={callback}>
          <Content {...props} />        </Profiler>
        <Profiler id="PreviewPane" onRender={callback}>          <PreviewPane {...props} />
        </Profiler>
      </Panel>
    </Profiler>
  </App>
);

補足

Profiler は軽いコンポーネントですが、必要な時にのみ利用すべきです。使うごとにアプリケーションに多少の CPU およびメモリオーバーヘッドが生じます。

onRender コールバック

Profiler には props として onRender 関数を渡す必要があります。 プロファイリングされているツリー内のコンポーネントが更新を「コミット」した際に、Raect がこの関数を毎回呼び出します。 この関数は、レンダー内容とかかった時間に関する情報を引数として受け取ります。

function onRenderCallback(
  id, // the "id" prop of the Profiler tree that has just committed
  phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
  actualDuration, // time spent rendering the committed update
  baseDuration, // estimated time to render the entire subtree without memoization
  startTime, // when React began rendering this update
  commitTime, // when React committed this update
  interactions // the Set of interactions belonging to this update
) {
  // Aggregate or log render timings...
}

それぞれを詳細に見てみましょう:

  • id: string - コミットが起きた Profilerid プロパティ。 複数のプロファイラを使用している場合にどのツリーにコミットが起きたのかを区別するのに使うことができます。
  • phase: "mount" | "update" - ツリーが初回マウントされたのか、props や state、フックの変更によって再レンダーされたのかを区別します。
  • actualDuration: number - 現在の更新で Profiler とその子孫のレンダーに要した時間。 これが(React.memouseMemoshouldComponentUpdate などの)メモ化をどれだけうまく有効に使えているかの指標となります。 理想的には、子孫要素は特定の props が変化した場合にのみ再レンダーされるため、初回マウント時以降にこの値は大幅に小さくなるはずです。
  • baseDuration: number - Profiler ツリー内のそれぞれのコンポーネントの直近の render 時間。 この値を使って最悪の場合のレンダーコスト(初回マウント時や、メモ化の一切ないツリーの場合)を見積もることができます。
  • startTime: number - 現在の更新のレンダーを React が開始した時刻に対応するタイムスタンプ。
  • commitTime: number - 現在の更新を React がコミットした時刻に対応するタイムスタンプ。 必要に応じてグループ化できるよう、1 コミット内のすべてのプロファイラ間でこの値は共有されます。
  • interactions: Set - 更新がスケジュールされた(rendersetState の呼び出しなどにより)際に trace された “interaction” の Set。

補足

更新の原因を特定するために interaction を利用可能ですが、trace 用の API は依然実験的です。

fb.me/react-interaction-tracing に詳細があります。