隨筆之如何判斷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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM