隨筆-10  評論-36  文章-6  trackbacks-0
              現在計算機的硬件設備的性能增長速度異常迅猛,使得越來越多的程序員開始不再關注代碼的執行效率,不再花費心思去構想精妙的算法,優化自己的代碼,導致設計的系統越來越龐大、越來越復雜,性能卻越來越差,程序員自己也逐漸淪落為藍領技術工人。一個經過簡單編碼培訓的人就可以勝任程序員的工作嗎?我認為不是這樣的。一個合格的程序員,除熟練掌握多種編程語言外,創造力才是程序員生命的源泉。而創造力并非天生的,需要豐富的經驗加勤奮的思考。本文并非想探討程序員的成長,只是將此作為引子,希望各位同仁能關注自己編寫代碼并能為之自豪,并以一個簡單的例子說明關注代碼優化問題導致的巨大性能提升。即使機器再好,一個編寫不良的代碼,依然難以達到理想的性能。
              今天測試人員向我抱怨,說我們提交的API代碼性能比較差,解析一個90萬筆業務的報文居然用了9個小時,這當然是不能接受的。我自己簡單測試下,發現在我的T43/1.5G機器上,API的解析速度只能達到每秒30筆,直觀覺得代碼應存在性能問題。我仔細查閱了程序,沒有發現明顯的問題。到底是什么導致性能損失的呢?我逐步跟蹤每步代碼的執行,終于找到了問題所在,簡單地講此性能問題是頻繁調用函數strlen()導致的。各位可能非常驚訝,我當時也很驚訝,但情況確實如此。90萬筆業務的報文長度約50M,解析報文時我們調用了自己編寫的底層代碼StrStrExt()替換系統的strstr()以便支持的GB18030漢字,而性能正是StrStrExt()底層函數導致的。
              先看看原始的StrStrExt()函數的代碼:
          // 查找含漢字串的位置
          char* StrStrExt(LPCSTR sSearch,LPCSTR sFind)
          {
              
          if (IsEmptyStr(sSearch)) return NULL;
              
          if (IsEmptyStr(sFind)) return (char*)sSearch;
              ULONG nOffset 
          =0;
              ULONG nIndex  
          =0;
              ULONG nMaxLen 
          = strlen(sSearch);
              ULONG nLen 
          = strlen(sFind);
              
          while(nOffset < nMaxLen)
              {
                  
          for(nIndex=0; nIndex<nLen; nIndex ++)
                  {
                      
          if(sSearch[nOffset + nIndex] != sFind[nIndex]) break;
                  }
                  
          if(nIndex == nLen) return (char*)(sSearch + nOffset);
                  
          int n = IsChineseChar(sSearch + nOffset);
                  
          if(n > 0)
                  {
                      
          // 漢字處理
                      nOffset += n;
                  }
                  
          else
                  {
                      nOffset
          ++;
                  }
              }
              
          return NULL;
          }
               發現strlen()對大字符串可能導致性能問題后,我將該函數修改如下:
          char* StrStrExt(LPCSTR sSearch,LPCSTR sFind)
          {
              
          if (IsEmptyStr(sSearch)) return NULL;
              
          if (IsEmptyStr(sFind)) return (char*)sSearch;
              ULONG nOffset 
          =0;
              ULONG nIndex  
          =0;
          //    ULONG nMaxLen = strlen(sSearch);
              ULONG nLen = strlen(sFind);
          //    while(nOffset < nMaxLen)
              while(sSearch[nOffset] != 0)
              {
                  
          for(nIndex=0; nIndex<nLen; nIndex ++)
                  {
                      
          if(sSearch[nOffset + nIndex] != sFind[nIndex]) break;
                  }
                  
          if(nIndex == nLen) return (char*)(sSearch + nOffset);

                  
          int n = IsChineseChar(sSearch + nOffset);
                  
          if(n > 0)
                  {
                      
          // 漢字處理
          //            nOffset += n;
                      for(int ii=0; ii<n; ii++)
                      {
                          
          ++nOffset;
                          
          if(sSearch[nOffset] == 0break;
                      }
                  }
                  
          else
                  {
                      nOffset
          ++;
                  }
              }
              
          return NULL;
          }
              新函數與原函數的唯一差別是不再使用strlen()去獲取串的結束位置,而是直接通過\0結束符判斷串的結束位置。修改后的代碼在我T43的機器上,解析速度提高到每秒3000筆的速度,是原代碼的近100倍,達到了系統性能指標的要求。
              這個問題提示我們,程序員應時刻關注代碼的性能問題,對核心代碼編寫者更是如此。
          posted on 2008-01-06 12:39 飛鷹 閱讀(667) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 泰来县| 梅州市| 柯坪县| 繁昌县| 临西县| 当涂县| 呼和浩特市| 漠河县| 化州市| 阿拉尔市| 缙云县| 五莲县| 含山县| 宜春市| 吉林省| 东兰县| 甘德县| 屏边| 晴隆县| 惠水县| 浠水县| 信丰县| 抚宁县| 宁明县| 阿拉善右旗| 衡东县| 讷河市| 曲靖市| 兴安盟| 三原县| 宁德市| 湟中县| 平邑县| 三台县| 达日县| 五台县| 鹰潭市| 江陵县| 鲁山县| 溆浦县| 陆丰市|