隨筆-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 飛鷹 閱讀(668) 評論(0)  編輯  收藏

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


          網站導航:
           
          <2008年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 东方市| 周口市| 如皋市| 神农架林区| 开鲁县| 罗城| 桓仁| 济源市| 大邑县| 湟源县| 博爱县| 大安市| 林周县| 大埔县| 乐山市| 电白县| 通渭县| 长泰县| 九龙城区| 宜都市| 高密市| 获嘉县| 化州市| 南充市| 犍为县| 巴林右旗| 武定县| 夏津县| 利津县| 白朗县| 英吉沙县| 石狮市| 财经| 娄底市| 松阳县| 遂川县| 旅游| 紫云| 安新县| 大冶市| 盐津县|