GCDAsyncUDPSocketの落とし穴


最近のiOS / OS Xでは非同期処理はGCDを使って行うのがトレンドなので、AsyncUDPSocketよりもGCDAsyncUDPSocketを使ったほうが良いだろうと思って使ってきたのですが、一部プロジェクトでは結局AsyncUDPSocketを使う形に戻すことになりました。

処理の優先度と安定さ

UDPではパケロスが発生したりパケットの順番が入れ替わったりします。パケロスや順番の入れ替わりが発生する要因は様々ですが、パケットの受信キューの「詰まり」もこれの原因となります。

特にリソースにそこまで余裕がないiOS端末で大量のUDPパケットを送受信しようとすると、処理が追いつかずに受信キューが詰まって不安定になることが珍しくありません。従って、UDP通信の安定性が求められる場合、UDP関連の処理の優先度をあげておかないとプログラムがうまく動作しないことがあります。

スレッドとGCD

AsyncUDPSocketでは、アプリケーション側のコード(AsyncUDPSocketクラスの外側)からpthread_setschedparamを使うことで受信のスレッドの処理の優先度を高く設定することができます。

struct sched_param param;
param.sched_priority = sched_get_priority_max(2);
pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);

GCDでもdispatch_set_target_queue等を駆使することで、処理の優先度を調整することは可能ですが、GCDAsyncUDPSocket内部のコードを書き換える必要があるため、面倒です。

結論

パケット数が少ないアプリ、あるいはリソースに余裕があるOS Xマシンではあまり問題が起きないかもしれませんが、パケット数が多いアプリ、iOSアプリではGCDAsyncUDPSocketよりもAsyncUDPSocketを使った方が良い場合がありそうです。


「GCDAsyncUDPSocketの落とし穴」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です