その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

NSNotification, NSNotificationCenter によるオブジェクト間通知のパフォーマンス

NSNotification, NSNotificationCenter を用いたオブジェクト間連携は使いやすいのでついつい多用してしまうのですが、具体的に内部でどのような処理が行われていて、パフォーマンス面での影響はどのくらいなんだろう、ということをイメージできずにいたので、調べてみました。


で、下記のような超わかりやすいAppleの日本語ドキュメントを発見しました。


Cocoa Fundamentals Guide: 通知


その中でパフォーマンス面について勉強になった箇所を抜粋します。

通知センターは、オブザーバに対して通知を同期的に配信します。通知の送信すべてが完了するまで、送信側のオブジェクトには制御は戻りません

通知メカニズムは、オブジェクト状態の変化を監視するための、Cocoaの唯一の選択肢ではなく、実際に多くの状況において、望ましい選択肢とはいえません。Cocoaのバインディングテクノロジー、特にそれを可能にしているキー値監視(KVO)プロトコルとキー値バインディング(KVB)プロトコルを使用することによっても、アプリケーション内のオブジェクトは他のオブジェクトのプロパティの変化を監視することができます。バインディングメカニズムは、通知よりも効率よくこの役目を果たします。バインディングでは、監視対象のオブジェクトと監視元のオブジェクトの間の通信がダイレクトに行われ、通知センターのような仲介オブジェクトを必要としません。さらに、バインディングメカニズムの場合、監視対象以外の変更に対しては、通常の通知のようなパフォーマンスへの影響がありません。

ただし、バインディングよりも通知のほうが好ましい状況もあります。オブジェクトプロパティの変更以外のイベントを監視したい場合があります。あるいは、KVOおよびKVBに準拠した実装が現実的でない場合があります。送信され、監視の対象となる通知の数が少ない場合は特にそうです。

通知の使用が正当化されるような状況であっても、パフォーマンスへの影響を認識しておく必要があります。通知を送信すると、最終的にはローカルの通知センターによって監視元のオブジェクトに同期的に配信されます。これは、送信が同期か非同期かに関係なく行われます。オブザーバが多数存在する場合や、通知の処理中に各オブザーバが大量の作業を行うような場合、プログラムは極端に遅くなることがあります。このため、通知を使い過ぎたり、効率の悪い使い方をしたりしないように注意する必要があります。

通知の使用についての次のガイドラインが、この目的に役立ちます。

  • アプリケーションが監視すべき通知を慎重に選択する。
  • 通知を受け取るための登録を行うとき、通知名と送信元オブジェクトを限定する。
  • 通知を処理するメソッドを、できる限り効率よく動作するように実装する。
  • 大量のオブザーバの追加と削除を避ける。いくつかの「仲介」オブザーバを使用して、オブザーバからアクセスできるオブジェクトに対して通知の結果を伝えるほうがよい