随笔之如何判断Android应用进程是否为单线程及闲扯多核并行编程

这篇文章来自公司的一封Q/A邮件。背景是想知道目前市面上的应用是否能在多核手机上性能有成倍增加。所以,自然而然就会问到一个基本问题,如何判断android中一个应用是否为多线程。

这里简单扯一下多核的知识。

我最早接触多核知识是2008年末到2009年初。背景很简单,我是做高性能网络数据传输服务器的,类似FTPServer一样。服务器的吞吐能力最好是随着CPU核数的增加成倍增长.。根据多核并行的知识,这是最理想的情况(有一个公式,可以计算性能和CPU核数的关系),但应用内部各个线程并非完全独立。即线程是独立运行在不同CPU核上,但是线程中所干的事情却在逻辑上有关系。例如运行在线程A上的函数等待运行在线程B上另外一个函数的执行结果。这样就导致性能不是随CPU核数线性增长。

根据上面的介绍,对于多核并行编程来说,最最重要的事情就是将你的应用中那些混淆不清的逻辑关系能拆成互不干扰或者互相牵连较少的模块,并让他们在不同线程上运行。这样就真正发挥多核的优势了。

听起来简单,真正实施的时候呢?

1 对于纯逻辑关系的问题,也就是非计算方面(即矩阵计算,编解码等),要想能掰叱清楚。难度很大。七大姑,八大姨的,能分那么清楚吗?目前,这方面的资料较少。

2 对于纯计算方面的问题,例如矩阵计算,要研究的就不是编码,而是数学,要把计算拆成各个小块,每个小块可单独运行在独立线程上,然后再汇总计算结果。这方面资料较多,如周伟明的《多核计算与程序设计》。编程角度看,OpenMP是一个多核并行计算的好库。(有人能尝试下用OpenMP来拆分逻辑工作吗?)

好了。多核的故事闲扯到这,对于纯逻辑关系问题,再扯的话就会扯到线程池,并发编程,异步IO,惊群效应,分布式内存管理等等等等。

下面来看如何判断Android应用进程为单线程还是多线程?请先思考,再看下面的答案:

1 android应用是运行在android环境中的,简单来说,是运行在dalvik虚拟机之上,而dalvik虚拟机本身是会创建一些线程,例如垃圾回收线程,JDWP调试线程

2 Android应用会经常利用binder和系统服务进行IPC通信,根据binder本身的特性,它会动态创建线程来完成外界请求。
以上两类线程都是应用不可控的,保守估计,这类不可控线程至少在3个左右
除了主线程之外的,就是应用自己是否会创建线程了。
查看一个进程中线程的方法有:
  1. ps,加一些参数(具体忘记了),可看某个进程下的线程及线程号,但无法区别是系统创建的线程还是应用自己创建的线程
  2. kill -3 对应进程pid,这个方法会向进程发送SIGQUIT消息,dalvik虚拟机会跟踪这个信号,并打印该进程所有线程的堆栈到一个文件
  3. 一般来说,java创建的线程都会有一个名字,例如binder线程就是Binder#0、Binder#1.通过这种方式可以区分哪些线程是系统创建的,哪些是应用创建的
  4. native代码(如Jni库)如果直接调用posix创建线程,则上述方法无法跟踪(如果该线程能回调到Java层,也可以获取信息),只能根据ps得到的信息,减去SIGQUIT得到的信息来判断了。不过这类线程一般都是应用自己创建的。

对于多核机器,apk如何发挥自己最大的性能,决定于两点:

1 dalvik虚拟机是否在多核机器上做到性能最优

2 apk自己的处理逻辑是否充分利用多核原理

上面是我对此Q/A的回答,欢迎各位看客积极参与argue。

posted @ 2012-07-27 22:23  innost  阅读(4937)  评论(5编辑  收藏  举报