【问题标题】:android - what is message queue native poll once in android?android - 什么是消息队列原生轮询在 android 中一次?
【发布时间】:2016-12-13 14:31:22
【问题描述】:

我知道线程有一个消息队列,并且处理程序能够向它们推送可运行对象或消息,但是当我使用 Android Studio 工具分析我的 android 应用程序时,有一个奇怪的过程:

android.os.MessageQueue.nativePollOnce

它比所有其他进程使用 CPU 更多。它是什么以及如何减少 CPU 花费在它上面的时间? 您可以在下面找到分析器结果。

【问题讨论】:

  • 看起来很忙。答案是不使用轮询。您没有发布有关您的应用程序的任何代码或其他信息。
  • 忙等待是什么意思?

标签: java android performance cpu profile


【解决方案1】:

简答:

nativePollOnce 方法用于“等待”直到下一个Message 可用。如果在此调用期间花费的时间很长,则您的主 (UI) 线程没有实际工作要做,而是等待下一个事件处理。无需担心。

说明:

因为“主”线程负责绘制 UI 和处理各种事件,所以 Runnable 有一个循环来处理所有这些事件。 循环由Looper 管理,它的工作非常简单:它处理MessageQueue 中的所有消息。

Message 被添加到队列中,例如响应输入事件、帧渲染回调甚至您自己的 Handler.post 调用。有时主线程没有工作要做(即队列中没有消息),这可能会发生,例如在完成单帧渲染之后(线程刚刚绘制了一帧并准备好下一帧,只需等待适当的时间)。 MessageQueue 类中的两个 Java 方法对我们来说很有趣:Message next()boolean enqueueMessage(Message, long)Message next(),顾名思义,从队列中获取并返回下一条消息。如果队列为空(并且没有任何内容可返回),则该方法调用native void nativePollOnce(long, int),该方法会阻塞直到添加新消息。此时您可能会问nativePollOnce 是如何知道何时醒来的。这是一个非常好的问题。当Message 加入队列时,框架调用enqueueMessage 方法,该方法不仅将消息插入队列,还调用native static void nativeWake(long),如果需要唤醒队列。 nativePollOncenativeWake 的核心魔法发生在 native (actually, C++) code 中。 Native MessageQueue 使用名为epoll 的Linux 系统调用,它允许监视文件描述符中的IO 事件。 nativePollOnce 在某个文件描述符上调用 epoll_wait,而 nativeWake 写入描述符,这是 IO 操作之一,epoll_wait 等待。然后内核从等待状态中取出epoll-waiting线程,线程继续处理新消息。如果您熟悉 Java 的 Object.wait()Object.notify() 方法,您可以想象 nativePollOnce 大致相当于 Object.wait()nativeWake 对于 Object.notify(),除了它们的实现方式完全不同:@987654357 @ 使用 epollObject.wait() 使用 futex Linux 调用。值得注意的是,nativePollOnceObject.wait() 都不会浪费 CPU 周期,因为当线程进入这两种方法时,它会因线程调度目的而被禁用(引用 Object 类的 javadoc)。但是,一些分析器可能会错误地将 epoll-waiting(甚至是 Object-waiting)线程识别为正在运行并消耗 CPU 时间,这是不正确的。如果这些方法实际上浪费了 CPU 周期,那么所有空闲的应用程序都将使用 100% 的 CPU,从而使设备发热并减慢速度。

结论:

您不必担心nativePollOnce。它只是表示所有消息的处理已经完成,线程等待下一个。好吧,这仅仅意味着你不会给你的主线程做太多的工作;)

【讨论】:

  • 如果队列中没有消息,nativePollOnce如何知道等待多长时间/何时唤醒?
  • @Florian 我刚刚更新了我的答案以提供更多详细信息(并纠正我原始答案中的一些不正确信息)。
  • 谢谢,太好了!
  • nativePollOnce() 不等待下一条消息。这是由 Java 'Looper' 类完成的。相反,它在内部调用 Linux epoll_wait 方法,该方法会等待一些 CPU 周期,这样循环不会导致 CPU 开销,并且 Android Looper 不会导致阻塞。
  • @linjiejun 指示主线程进行渲染工作的消息可能来自框架(例如输入事件等)或应用程序本身(例如当您安排动画时等)。有关更多信息,请参阅 Choreographer 类描述 (developer.android.com/reference/android/view/Choreographer)。
猜你喜欢
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多