web-dev-qa-db-ja.com

android-androidで一度メッセージキューのネイティブポーリングとは何ですか?

スレッドにメッセージキューがあり、ハンドラーがランナブルまたはメッセージをプッシュできることを知っていますが、Androidアプリケーションを使用してAndroid Studioツールを使用して、奇妙なプロセスがあります:

Android.os.MessageQueue.nativePollOnce

他のすべてのプロセスよりもCPUを使用します。それは何ですか、そしてCPUがそれに費やす時間をどのように減らすことができますか?プロファイラーの結果は以下で確認できます。

enter image description here

23
Sajad Norouzi

短い答え:

nativePollOnceメソッドは、次のMessageが使用可能になるまで「待機」するために使用されます。この呼び出し中に費やされた時間が長い場合、メイン(UI)スレッドは実行する実際の作業がなく、次のイベントが処理されるのを待ちます。それを心配する必要はありません。

説明:

「メイン」スレッドはUIの描画とさまざまなイベントの処理を担当するため、Runnableにはこれらすべてのイベントを処理するループがあります。ループは Looper によって管理され、その仕事は非常に簡単です: MessageQueue 内のすべてのメッセージを処理します。

Message は、たとえばフレームレンダリングコールバックまたは独自の_Handler.post_呼び出しとして、入力イベントに応答してキューに追加されます。メインスレッドに実行する作業がない(つまり、キューにメッセージがない)場合があります。 1つのフレームのレンダリングが終了した直後(スレッドは1つのフレームを描画し、次のフレームの準備ができているため、適切な時間だけ待機します)。 MessageQueueクラスの2つのJavaメソッドは、私たちにとって興味深いものです:Message next()およびboolean enqueueMessage(Message, long)Message next()、その名前が示すように、キューから次のメッセージを受け取って返します。キューが空の場合(何も返されない場合)、メソッドはnative void nativePollOnce(long, int)を呼び出し、新しいメッセージが追加されるまでブロックします。この時点でnativePollOnceがいつ目覚めるかをどのように知るかを尋ねるかもしれません。これはとても良い質問です。Messageがキューに追加されると、フレームワークはenqueueMessageメソッドを呼び出しますメッセージをキューに挿入するだけでなく、キューをウェイクアップする必要がある場合はnative static void nativeWake(long)も呼び出します。nativePollOncenativeWakeのコアマジックは- ネイティブ(実際にはC++)コード 。ネイティブMessageQueueは、 epoll という名前のLinuxシステムコールを利用して、IOイベント。nativePollOnceは特定のファイル記述子で_epoll_wait_を呼び出しますが、nativeWakeはIOの1つである記述子に書き込みます=演算、_epoll_wait_待機します。次に、カーネルはepoll待機スレッドを待機状態から取り出し、スレッドは新しいメッセージの処理を続行します。 JavaのObject.wait()およびObject.notify()メソッドに精通している場合は、nativePollOnceObject.wait()およびnativeWake for Object.notify()、ただし完全に異なる方法で実装されている場合を除く:nativePollOnceepollを使用し、Object.wait()futex Linux呼び出し。 nativePollOnceObject.wait()もCPUサイクルを浪費しないことに注意する必要があります。スレッドがどちらかのメソッドに入ると、スレッドスケジューリングの目的で無効になります(Objectのjavadocを引用)クラス)。ただし、一部のプロファイラーは、epoll-waiting(またはObject-waiting)スレッドが実行中であり、CPU時間を消費していると誤って認識する場合がありますが、これは正しくありません。これらの方法が実際にCPUサイクルを無駄にした場合、アイドル状態のアプリはすべてCPUを100%使用し、デバイスを加熱および減速します。

結論:

nativePollOnceについて心配する必要はありません。すべてのメッセージの処理が完了し、スレッドが次のメッセージを待つことを示しているだけです。まあ、それは単にあなたがメインスレッドにあまり多くの仕事を与えないことを意味します;)

34
Lawiusz