<output id="yn1pw"></output>
    <wbr id="yn1pw"></wbr>

    <form id="yn1pw"><legend id="yn1pw"></legend></form>

  1. 更多課程 選擇中心

    嵌入式培訓
    達內IT學院

    400-111-8989

    嵌入式系統的性能該如何優化和進步?

    • 發布:嵌入式培訓
    • 來源:嵌入式教程
    • 時間:2017-12-29 16:05

    嵌入式系統的啟動速度因設備的性能和代碼的質量而異,但總體而言,從消費者的角度考慮,系統的啟動速度肯定是越快越好。因此,對嵌入式系統進行性能優化,加快設備的啟動時間為項目后期必須進行的一項工作。需要注意的是:嵌入式Linux設備的優化不是一蹴而就的,而是一個不斷優化,不斷改進的過程。

    啟動快慢的標準

    設備啟動的快慢目前還沒有一個統一的標準。在項目中一般按照客戶的標準。

    性能的評測

    對于開發人員來說,評價設備的性能一般是通過在代碼中增加log的方式。這種方式具有以下幾點優點:

    1.精確度高

    通常能夠精確到毫秒。有特殊需求的情況下,可以精確到毫秒,比如使用gettimeofday函數。

    2.靈活性強

    可以測出代碼中任意部分的代碼運行所耗費的時間。

    在嵌入式設備中,導入設備啟動時間過長,性能低下的原因一般包括如下幾個方面:

    1.硬件的原因

    硬件的原因一般指的是設備的CPU及Flash性能。如果代碼的運算量很大,礙于CPU和Flash的性能,會導致CPU過于繁忙。有些設備礙于成本的原因,Flash太小,很多東西都需要壓縮存放,那么在設備啟動過程中,解壓也需要一定的時間。

    2.程序的原因

    代碼需要進行大量的IO操作,比如讀寫文件,內存訪問等等,CPU更多的時候處于等待狀態。而有些代碼,由于編寫的原因,導師各個進程之間相互等待,CPU利用率低下,制約了設備的性能。

    優化的原則

    優化并不能盲目的優化,盲目追求性能,還要統籌考慮。一般要遵循以下原則:

    1.等效性原則

    優化前后的代碼實現的功能要完全一致。

    2.有效性原則

    優化后的代碼一定要比原先的代碼運行速度快,占用存儲空間小,或者二者兼有,否則就是毫無意義的優化。

    3.經濟性原則

    很多代碼性能低下的部分原因也是由于硬件性能的限制,比如將文件壓縮存放以節約存儲成本。優化要在現有的條件下考慮,不要以更換存儲空間的大小來換取解壓的時間。優化要付出較小的代價,很多程序員在做優化的時候,抱怨設備的性能有限,要求提高設備的性能,這樣只能是本末倒置。

    優化的方法

    此處提出的優化的方法主要是從代碼的角度考慮,不包括升級硬件。

    shell 腳本優化:

    絕大多數的嵌入式設備都會使用busybox作為實現Linux命令的工具,因此BusyBox提供了一個比較完善的環境,可以適用于任何小的嵌入式系統。

    BusyBox 是一個集成了一百多個最常用linux命令和工具的軟件。BusyBox 包含了一些簡單的工具,例如ls、cat和echo等等,還包含了一些更大、更復雜的工具,例grep、find、mount以及telnet。有些人將BusyBox稱為Linux工具里的瑞士軍刀。簡單的說BusyBox就好像是個大工具箱,它集成壓縮了Linux的許多工具和命令,也包含了Android系統的自帶的shell。

    BusyBox包含三種類型的命令:

    APPLET

    即為人所熟知的applets,它由BusyBox創建一個子進程,然后調用exec執行相應的功能,在執行完畢后,返回控制給父進程。

    APPLET_NOEXEC

    系統將調用fork創建子進程,然后執行BusyBox中相應的功能,在執行完畢后,返回控制給父進程。

    APPLET_NOFORK

    它相當于builts-in,只是執行BusyBox的內部函數,不必創建子進程,所以其效率極高。

    眾所周知,在Linux中調用fork,exec是很耗費時間的,所以我們應該盡可能的使用APPLET_NOFORK命令,其次是APPLET_NOEXEC,最后是APPLET。

    在BusyBox1.9中,屬于APPLET_NOFORK的功能有:

    屬于APPLET_NOEXEC的功能有:

    所以優化shell腳本的策略一般有:

    優化進程啟動速度

    進程的啟動過程如下:

    要加快的進程的啟動速度,可以從以下幾方面入手:

    1.減少加載的動態庫的數量

    a) 使用dlopen,將啟動時不需要的動態庫延后加載

    b) 將一些動態庫改為靜態庫

    優點:減少了加載動態庫的數量;在與其他動態庫合并之后,動態庫內部的函數之間不必再進行動態鏈接、符號查找,從而提高速度

    缺點:該動態庫如果被多個動態庫或進程所依賴的話,那么該動態庫將被復制多份合并到新的動態庫中,導致整體的文件大小增加,占用更多的Flash。

    失去了動態庫原有的代碼段內存共享,因此可能會導致內存使用上的增加。

    2 優化加載動態庫時的搜索路徑

    a) 設置LD_HWCAP_MASK,禁掉一些不用的硬件特性。

    b) 將所有的動態庫都放在一個目錄下,并且將目錄放在LD_LIBRARY_PATH的開始。

    c) 不能放在一個目錄下,在進程中加入-rpath選項,指定搜索路徑。如果做了之前的工作仍然無法滿足進程啟動速度的要求,那就從進程的調度上下功夫,可以:進程改為線程;可以把原來的進程分割為兩個部分。

    常駐內存部分:其為daemon進程,主要負責加載進程所需要的動態庫,偵聽用戶信號,創建和銷毀用戶邏輯線程。完成用戶邏輯部分: 由daemon部分創建線程,按用戶需求完成用戶邏輯,這樣就節省掉了加載動態庫、初始化動態庫和全局變量部分,可以縮短進程的響應時間,來滿足用戶的需求。

    還可以再引申一下,將原來的多個daemon進程的常駐內存部分進行合并,根據用戶邏輯需求,創建不同的進程。

    優點:創建線程時,不需要重新加載動態庫,故縮短了進程的響應時間;多個業務邏輯共享動態庫時,避免了系統為每個業務邏輯創建動態庫的數據段,從而節省了大量的內存。

    缺點:由原來的進程改為線程,工作量比較大,代碼修改上存在一定的風險,多個業務邏輯線程之間共享動態庫時,有可能會帶來全局變量的沖突。

    由于還是存在daemon進程部分,所以其堆棧內存不會被釋放,多個業務邏輯線程所存在內存泄露會糾纏在一起,從而使問題更加復雜。

    3.preload進程

    在進程的main函數中插入一行語句:

    pause();

    這樣,當進程啟動時,加載完動態庫后,就會停在這里,不會運行用戶邏輯。當我們需要相應用戶時,向該進程發送一個信號,這樣用戶就會繼續前進,處理用戶邏輯,這樣就節省了進程加載動態庫的過程。

    當用戶邏輯執行完成后,就退出進程,同時再啟動該進程,這是進程會在加載完動態庫后,停留在那里。

    提前加載,延后退出。

    當進程啟動需要較長時間時,很多程序員僅僅想到了將其提前加載(在開機時啟動),卻沒有想到退出條件,而導致進程中又多了一個daemon進程。 因此提前加載,延后退出需要更加精確的控制進程的生命周期。

    調整CPU頻率:

    嵌入式設備中,CPU一般有幾個工作頻率

    CPU頻率越高,運行速度越快,耗電量越高

    可以再啟動前調高CPU頻率,在完成后再調低CPU頻率

    這種方法以耗電量增加為代價,在某些場合下不適用

    4.優化代碼

    if表達式

    從左到右對表達式求值,當結果確定后也就不在需要計算其他的表達式,也就是常說的“短路”機制,因此對于if語句可以做以下優化:

    刪除冗余條件

    刪除肯定不成立的條件

    利用短路機制,將計算速度最快的表達式放在左邊

    循環語句的優化:

    將不變的代碼移到循環之外

    將分支語句提到循環的外面

    通過循環分支的展開,可以降低循環次數,從而減少分支語句對循環的影響

    用減1指令替代循環加1指令

    寄存器的使用遵循ATPCS標準。

    ATPCS標準是嵌入式開發應盡量遵循的標準。

    子程序間通過寄存器R0——R3來傳遞參數。

    被調用的子程序在返回前無需恢復寄存器R0——R3的內容。

    在子程序中,使用寄存器R4——R11來保存局部變量。

    如果在子程序中使用了寄存器R4——R11的某些寄存器,子程序進入時必須保存這些寄存器的值,在返回前必須恢復這些寄存器的值,對于子程序中沒有用到的寄存器則不必進行這些操作。

    R12用作子程序間scratch寄存器,記作ip。

    在子程序間的連接代碼段經常使用這些規則。

    R13用作數據棧指針,記作sp。

    在子程序間寄存器R13不能用作其他用途。

    R14成為連接寄存器,記作lr。

    它用來保存子程序的返回地址。

    R15是程序計數器,記作pc。

    子程序返回結果為一個32位整數時,可以通過寄存器R0返回;結果為一個64位整數時,可以通過寄存器R0和R1返回,以此類推。

    5.函數參數優化

    函數的參數最好不超過4個;4個以下的形參可以通過寄存器來傳遞,4個以上的參數,則需要通過棧來傳遞。同時,如果參數小于4個,R0-R4中剩余的寄存器可以保存函數中的局部變量。

    6.減少局部變量的個數

    盡量限制函數內部循環所用的局部變量的數目,最多不超過12個,以便編譯器能把變量分配到寄存器。

    如果沒有局部變量保存到棧中,系統也將不必設置和恢復棧指針。

    當函數內部寄存器變量多于12個時,并不意味著只是將前面的12個臨時變量分配寄存器,之后的臨時變量都是通過棧內存來操作。

    當寄存器分配完內存后,遇到新的臨時變量時,先查看已分配寄存器的局部變量是否有在后面的代碼中不會被使用,則新的局部變量使用其所占用的寄存器。如果也紛紛寄存器的局部變量在后面的代碼中都要使用,則要選擇出一個臨時變量,將其保存到棧中,之后將其使用的寄存器分配給局部變量。

    7.文件操作的優化

    讀寫文件時,緩沖區的buffer為2048或4096時,速度最快

    利用mmap讀寫文件

    mmap的基本流程是:

    8.線程的優化

    線程的創建是要付出代價的,如果創建的線程只做很少的事情,而又頻繁的創建和銷毀線程,是得不償失的

    使用異步IO,來取代多線程+同步IO的方式

    使用線程池取代線程的創建和銷毀

    9.內存操作的優化

    內存訪問流程 :

    CPU試圖訪問一塊內存

    CPU首先確認該內存是否已經被加載到cache中

    如果加載到cache中,則直接在cache中定位

    如果未加載到cache中,則通過CPU和內存直接的地址總線,向內存發送地址的高27位地址

    當內存收到高27位地址后,利用SDRAM的突發交換模式,將連續的32個字節傳送給CPU的cache,填充一個緩存行

    CPU可以通過地址的高27位來定位cache的緩存行,利用地址的低5位定位到緩存行中具體的字節

    盡量使用占用內存少的算法

    利用流水線內存存取與計算并行的特點,組合內存訪問與計算

    10.調整進程的優先級

    Linux支持兩種進程:實時進程和普通進程。

    實時進程的優先級是靜態設定的,而且始終大于普通進程的優先級。對于實時進程來講,其使用絕對優先級的概念,絕對優先級的取值范圍是0——99,數字越大,優先級越高。

    普通進程的絕對優先級取值是0。在普通進程之間,其又具備靜態優先級和動態優先級之分。靜態優先級,我們可以通過程序來修改。同事系統在運行過程中,會在靜態優先級基礎上,不斷動態計算出每個進程的動態優先級,擁有最高動態優先級的進程進程被調度器選中。一般來講,靜態優先級越高,進程所能分配的時間片越長。

    盡量不要把某些進程放到啟動腳本中,嘗試daemon進程在第一次使用時啟動。

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:嵌入式開發工具:jetty介紹和使用
    下一篇:一位嵌入式er學習ucos和ARM體系結構的心得體會

    裸編程怎么做?裸編程具體做法

    嵌入式編程中你必須知道的小知識

    嵌入式C語言編程小知識總結

    有哪些工具可以讓嵌入式開發事半功倍?

    • 掃碼領取資料

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    高清在线不卡一区二区_2019最新国产高清不卡a_亚洲欧洲日本aⅴ 百度 好搜 搜狗
    <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>