2010-08-02 64 views
1

我有一個需要處理字節數組源的程序。當字節數組大小爲3000字節時,本來程序工作正常。現在數據量增加,陣列大小需要從3000變爲30000(10次)。讀取字節數組時意外的長處理時間

我做了一個樣本基準程序來測試循環時間。我認爲所需的CPU時間應該根據陣列大小線性增加,但基準程序顯示,與過程3000字節相比,進程30000字節需要多於35倍。

這是我的基準測試程序。程序是否可以改進,使其僅使用大約10倍的CPU時間?

public static void main(String args[]) 

    int TestArraySize=30000; 
    String strFinalMessage=""; 

    // create a dummy byte array 
    byte[] bytearrayMessageContent = new byte[TestArraySize]; 
    for (int i=0; i<TestArraySize; i++) { 
     // fill character A-J into the dummy array 
     bytearrayMessageContent[i] = (byte) (i%10+65); 
    } 
    System.out.println(bytearrayMessageContent.length); 

    // time start time 
    long lngCurrentTime = System.currentTimeMillis(); 

    // process the byte array 
    int intTHMessageLenAdj = TestArraySize; 
    try { 
     InputStream input = new ByteArrayInputStream(bytearrayMessageContent); 
     while (intTHMessageLenAdj > 0) { 
      // get random length of bytes to process 
      int RandomLength = getNextRandom(); 
      if (RandomLength > intTHMessageLenAdj) { 
       RandomLength = intTHMessageLenAdj; 
      } 

      // get the bytes to be process in a byte array and process it 
      byte[] bytearrayMsgTrunk = new byte[RandomLength]; 
      input.read(bytearrayMsgTrunk); 
      // do some logic here 
      strFinalMessage += new String(bytearrayMsgTrunk) + "||"; 

      // repeat looping until all bytes are read 
      intTHMessageLenAdj -= RandomLength; 
     } 
     input.close(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 

    // time end time 
    lngCurrentTime = System.currentTimeMillis() - lngCurrentTime; 
    //System.out.println(strFinalMessage); 
    System.out.println(lngCurrentTime); 
} 

public static int getNextRandom() { 
    // info is arround 4 bytes size 
    Random random = new Random(); 
    return random.nextInt(8); 
} 
+1

也許使用一個stringbuilder? – 2010-08-02 09:25:21

回答

2

好了,這裏還有幾個問題:

  • 您使用的是默認的平臺編碼字符串。不要這樣做。指定特定的字符串編碼以在字節和文本之間進行轉換。
  • 不要像這樣在循環中連接字符串 - 請使用StringBuilder
  • 您忽略InputStream.Read的返回值。從ByteArrayInputStream閱讀時這可能是好的,但你通常不應該依賴它。
  • 您每次創建一個新的Random實例。我相信在Java 6中這是好的,但會在早期版本中給你重複的值。基本上,這通常是一個糟糕的主意。重複使用Random的一個實例。
+0

他在每次調用getNextRandom時創建一個新的Random對象() – 2010-08-02 09:28:59

+0

@Thomas:是的,我發現在我最近的編輯:) – 2010-08-02 09:30:14

2

我想所需的CPU時間應線性地根據陣列大小被增加,但基準程序表明處理30000個字節需要太多的比較處理3000個字節超過35倍。

其實,我期望它隨着數組大小的增加而呈二次方式增長。如果您要對該計劃進行簡介,您可能會發現有相當比例的時間正在致電String.concat。隨着陣列變大,比例會增加。

基本上,每次你做一個字符串連接時,你將你迄今積累的所有字符複製到一個新的字符串中...並丟棄前一個字符。不難看出代碼的那部分是O(N**2),其中N是數組大小。

替換字符串聲明和級聯這一點:

// allocate the builder with extra space to hold the '||' characters 
StringBuilder sb= new StringBuilder(TestArraySize * 3/2); 
... 
// this replaces the concatenation. 
sb.append(new String(bytearrayMsgTrunk); 
sb.append("||"); 
... 
// this does a final copy of the characters to create a new String 
String strFinalMessage = sb.toString(); 
0

爲什麼你認爲你需要增加緩衝區的大小,因爲數據量的增加?事實並非如此。