2

我有一些代码使用 Jsoup 来获取和解析一些 html 页面,然后我操作 html 树,然后将其传递给绘制它的 WebView。如果我绕过我的操作,代码在 Android SDK 模拟器上以可接受的时间(2-3 秒)运行,但是当我进行操作时,时间会跳到不可接受的程度(大约 60 秒才能加载一个页面!)。

使用 Eclipse 和 Android SDK 我对运行进行了分析,现在我正在尝试解释结果。从这里http://android-developers.blogspot.com/2010/10/traceview-war-story.html获得了对“独占 Cpu 时间 %”的配置文件进行排序的提示。令我惊讶的是,我自己的代码甚至没有列出 1%。使用时间最多的是 android.view.ViewGroup.drawChild(),占 11.9%。列出的第一个非 android 函数(按独占 cpu % 排序)是 java.lang.ref.Reference.get(),它以 0.4% 列出。

但我想最奇怪的是我自己的代码,我只能找到我的 AsyncTask 的 doInBackground() 列出;依次调用的函数甚至都不存在,即使我可以通过调试输出看到它们被调用。为什么那些没有列出?

我不明白该怎么做。非常感谢任何提示。

4

1 回答 1

2

Although I don't have a reference at hand, I think it's safe to assume that Android executes AsyncTask.doInBackground() in a Thread with priority android.os.Process.THREAD_PRIORITY_BACKGROUND

This means that this Thread is scheduled in the context of a Linux cgroup (scheduling class) for which -- always or under frequent circumstances, I'm not sure and have read various claims -- an upper bound of common CPU time of 5% or 10% -- again, different sources make different claims -- is applied.

In other words, all background threads have to share 5% or 10% of the available CPU time. Again, I have read claims that this is dynamically adjusted if the foreground and real time tasks are idle, but I'd be happy to be pointed to a credible source myself. Also, I wouldn't count on it since the user can listen to a real time audio stream while using my app.

If you adjust the background Thread's priority, like so:

private static final int bgThreadPrio = Process.THREAD_PRIORITY_BACKGROUND +
                                        Process.THREAD_PRIORITY_MORE_FAVORABLE;
protected YourReturnType doInBackground() {
    Process.setThreadPriority(bgThreadPrio);
    ....
}

then you achieve two things.

  • You lift the Thread out of the background cgroup such that it does not have to share 10% of CPU time with the other background threads (at least currently, until Android changes its policies in this regard).
  • You assign a priority to the Thread which usually will not have an extremely bad impact on User Interface and Real Time threads, because THREAD_PRIORITY_DEFAULT is 0 while THREAD_PRIORITY_BACKGROUND is 10. So your Thread will run at priority 9 which is much worse than 0 but it will avoid the artificial limit of the background tasks.

However, you also probably change the priority of the Thread which the underlying AsyncTask executor provides for your AsyncTask. This Thread is going to be recycled, and it may be a single Thread or chosen from a pool. So it might be a good idea to set the priority in all doInBackground() methods in all AsyncTasks in your app.

于 2013-01-08T11:42:35.863 回答