程序性能優化(一)

經過設計合理的數據結構和算法將一些本須要在運行期間計算的信息預先存放在內存中來提高性能,是一種空間換時間的優化,下面一些實際的例子描述了這種優化方法的使用:html

  • 在一個遞增的數組中查詢和待查找元素最接近的的索引

例如數組[1,2,3,4,5],待查找元素爲1.1返回數組索引0,待查找元素爲1.6返回數組索引1,經過計算和數組每一個元素的差值,循環遍歷一遍數組能夠便可獲得索引值,以下代碼所示:算法

const double g_searchTable[] = {1,2,3,4,5};

int getIndex(double data)
{
    int index = 0;
    double temp;

    double temp1 = fabs(g_searchTable[0]-data);

    for(int i=0;i<sizeof(g_searchTable)/sizeof(g_searchTable[0]);i++)
    {
        temp = fabs(g_searchTable[i]-data);
        if(temp < temp1)
        {
            temp1 = temp;
            index = i;
        }
    }

    return index;
}
View Code

該代碼在循環內部存在浮點數計算、計算絕對值並且要遍歷數組,若是數組足夠大且頻繁調用程序性能必然低下。咱們能夠經過把非遞減的數組元素當作一個連續區域中的幾個位置,計算出各個位置間的中點,劃分爲不一樣的區間,便可經過比較待待查找的元素落在什麼區間中得出索引值。入下圖所示若是待查找元素小於1.5返回索引0。這裏就須要咱們增長一個區間數組[1.5,2.5,3.5,4.5],在代碼中直接跟元素比較便可獲得索引信息。數組

const double g_searchTable[] = {1,2,3,4,5};
const double g_searchDivTable[] = {1.5,2.5,3.5,4.5};

int getIndex1(double data)
{
    int index = 0;

    for(int i=0;i<sizeof(g_searchDivTable)/sizeof(g_searchDivTable[0]);i++)
    {
        if(data < g_searchDivTable[i])
        {
            return i;
        }
    }

    return sizeof(g_searchDivTable)/sizeof(g_searchDivTable[0]);
}
View Code

經過增長一個對應的區間數組空間,咱們消除了浮點運算、絕對值計算,而且在肯定待查元素的區間後便可獲得結果,不用繼續遍歷數組。性能優化

  • switch語句的編譯優化

咱們在代碼中常常使用switch語句,其結構清晰,經過計算表達式的值跳轉到指定的case分支中,在編譯過程當中每每並非將表達式同case常量依次比較來定位到具體分支中,這樣的效率每每很低下,編譯器一般使用了「跳轉表技術」來定位分支目標地址。跳轉表能夠當作一個地址數組,其中每個元素表示一個代碼段的地址,經過映射表達式值爲跳轉表中的索引便可獲取對應的目標地址。以下switch語句:數據結構

switch(n)
{
  case 5:   //ADDR1
  case 7:   //ADDR2
  deafult:  //DEFAULT_ADDR
}

編譯器每每轉換爲以下跳轉表:數據結構和算法

JumpTable = [ADDR1, DEFAULT_ADDR, ADDR1];

int index = n-5;
if index >2
    goto DEFAULT_ADDR

goto JumpTable [index]

經過使用跳轉表技術,增長跳轉表的空間消耗,能夠直接定位到目標地址。ide

  • 字符串到系統標示符的映射

在一些系統中咱們每每須要將一系列的字符串轉換爲系統對應的標示符,例如編譯器的分詞模塊對輸入的「int」字符串轉換爲系統的TK_INT類型。系統中默認的標示符每每不少,若是對輸入字符串經過代碼分支依次比較將十分耗費時間。爲了提高效率咱們能夠考慮經過使用hash技術,選取合適的散列函數將字符串轉換爲一個映射數組的下標。下面代碼將「add」、「sub」、「mul」、「div」轉換爲系統的對應類型:函數

typedef enum
{
    T_ADD,
    T_SUB,
    T_MUL,
    T_DIV,
    T_ERR
}Token;
typedef struct
{
    char* str;
    Token tk;
    char nextFlag;
}MAP_T;

MAP_T map0[] = {{"add",T_ADD,1},{"sub",T_SUB,1},{"mul",T_MUL,0}};//「add」、「sub」、「mul」經過散列函數計算出相同的數組下標0
MAP_T map1[] = {{"div",T_DIV,0}};//「div」經過散列函數計算出數組下標1
//映射信息
MAP_T* hashTable[] = {map0,map1};

Token getTk(char* str)
{
    int index = -1;
    MAP_T *pMap = NULL;

    index = getHashCode(str);
    pMap = hashTable[index];

    while(1)
    {
        if(0 == strcmp(str,pMap->str))
        {
            return pMap->tk;
        }
        if(0 == pMap->nextFlag)
        {
            break;
        }
        pMap++;
    }
    return T_ERR;
}
View Code

入上所示,咱們保存了全部字符串和系統標示符的對應關係,計算待轉換字符串的hash值便可快速定位到一個小的區間中。經過選取適當散列函數能夠的獲得更好的效率。這裏使用了鏈地址法來解決hash衝突。性能

 

以上實例都是基於空間換時間的優化方式,經過設計合理的數據結構,保存關鍵的信息,能夠極大的對程序性能優化。優化

轉載請註明原始出處:http://www.cnblogs.com/chencheng/p/3372945.html

相關文章
相關標籤/搜索