獵: Embedded System?所以你摸過Linux或者android嗎?
我: 我之前碰的OS都是偏embadded OS
獵: 那你之前做過Driver嗎?
我: 我做得比較上層一點
獵: 所以是偏AP跟MMI?
我: 也不是,主要是system跟framework
獵: 所以那是?
我: 就~~~Embedded system
獵: 怒~~~~
為了避免再過一陣子連我自己都忘了以前做了什麼Embedded system,還是記一下好了
Performance: 為何我們的手機跑起來比IPhone慢?
沒錯,在當初做手機IC的turnkey solution時,老闆就給了這麼一個作業,當時的我很想說: 我們家IC開的規格不夠快,IP又包得不夠多,怎麼跟蘋果比啊??但是又想到我們家是用做Embedded System(非general-purpose computing)平台去山寨IPhone以及安卓這種幾乎是general-purpose computing的平台(又是多核心,又是GPU的),所以只好認命開始想招式.
軟體在效能改進有什麼招呢? 通常最容易上手的就是空間換時間的方式,不管是pre-load或者cache都有顯著效果,不過這招在cost-down需求出現的時候,基本上就破功了.
比較根本的處理方法就是先profiling出bottleneck(profiling也有很多工夫可以討論,在這裡就不寫了),再從造成bottleneck的critical function進行改善.
改善方案可能是設計演算法,或者配合processor以及compiler機制做改,例如:
- Loop unrolling: heavy function中,考量ARM的loop overhead而把迴圈內的一行assign細拆成多步assign,可能會獲得較好的結果(不過如果compiler本身優化做得好,就不用自己這樣寫)
- 考量ARM在load function時,會把前四個參數放進暫存器中,則把被大量使用的參數放在前四個
- 想辦法讓D-cache的效果不打折. 例如考量cache alignment下,重新排序local變數或者structure;甚至於特殊情況下主動做clean cache來避免反覆的cache miss
- 更多細節,可以自己參考[ARM System Developer's Guide: Designing and Optimizing System Software]這本書
Memory: 又要馬兒好,又要馬兒不吃草
前面講到可以利用空間換時間的方法來提升效能,可是老闆這時可能又會繼續問你: 雖然效能改善了,但是可以多省點記憶體嗎?客戶需要個cost down的方案聽到這,工程師的腦神經似乎又斷線了: "記憶體現在才多少錢!!才差個零點幾塊美金也要搞到大家雞飛狗跳,不停加班!!"
不過如果你有經驗跟業務一起跑過客戶,聽到客戶就是緊抓著那零點幾塊美金的BOM差異找碴,也知道各家方案的價差往往就是在那幾塊美金之間廝殺(不要以為IC生意就不是紅海),你就會體會出嵌入式設備的市場上"價格才是硬道理"的現實.
那麼省記憶體又有哪些招呢? 先寫一些我還有印象的例子
- compile time設定的data alignment,會讓compiler自己幫忙把structure補上padding以滿足alignment. 為了避免被插入無用padding的浪費,需要把structure內的element合理的重新排序塞好,減少被插入padding
- 利用union或者bit field的定義,把structure內的element塞到更緊(bit field需要考量compiler支持程度,有可能沒用或者造成效能影響)
- 不要在function中直接宣告一個很肥的local variable(請去heap中配置),造成stack memory不必要的浪費(我就幫忙"第二手"解過這種情況造成的stack overflow,因為前一棒在沒有找出root cause的情況下,居然是把stack size放大來解問題)
Debug: 如果沒有GDB,也沒有JTAG
如果是Embadded linux開發,講到debug你會說不就是用GDB嗎? 不過對於非linux的小型系統,可能就沒有這樣的remote debugger可以用.如果做過driver的人,你可能會說那就用JTAG啊! 是啊,通常embadded system都會支持JTAG,不過並不是人人都有一台trace32可用,如果老闆認為你的單位應該不需要用到,或者貴公司很省錢(想當初我在小m從不認為能借到trace32,卻聽說大M幾乎人手一台時,心中真是感慨),你還是得訓練各種debug方法
- print log永遠是個方法. 不要以為這方法很蠢,這是個訓練邏輯分析的方法. 例如我曾經幫人看一個不知名兇手亂釋放記憶體造成死機的問題,結果花了半天用print log的方式找出真兇
- 利用stack內的資訊推理各種線索. 如果死機時,你手邊只有各task的stack memory raw data,你可能需要利用link info配合raw data還原出call stack; 你也可能需要利用function的assembly code配合raw data還原出call stack中的各個變數值
- 研究各種heap被踩爛的死狀. 通常記憶體內容被破壞是system crash的一大死因,所以你得像柯南一樣,從死亡現場(heap raw data),配合事件發生前後的情境(task schedule history, task event history),推理出真正的元兇
0 意見:
張貼留言