Java 读取字节数组时出现意外的长处理时间

Java 读取字节数组时出现意外的长处理时间,java,arrays,byte,Java,Arrays,Byte,我有一个程序,需要处理字节数组源代码。最初,当字节数组大小为3000字节时,程序工作正常。现在,数据大小增加,阵列大小需要从3000更改为30000 10次 我制作了一个示例基准程序来测试循环时间。我认为所需的CPU时间应该根据数组大小线性增加,但基准测试程序显示,处理30000字节所需的时间比处理3000字节所需的时间多得多 这是我的基准计划。程序是否可以改进,使其仅使用大约10倍的CPU时间 public static void main(String args[]) int Te

我有一个程序,需要处理字节数组源代码。最初,当字节数组大小为3000字节时,程序工作正常。现在,数据大小增加,阵列大小需要从3000更改为30000 10次

我制作了一个示例基准程序来测试循环时间。我认为所需的CPU时间应该根据数组大小线性增加,但基准测试程序显示,处理30000字节所需的时间比处理3000字节所需的时间多得多

这是我的基准计划。程序是否可以改进,使其仅使用大约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);
}

嗯,这里有几个问题:

您正在对字符串使用默认的平台编码。不要那样做。指定要在字节和文本之间转换的特定字符串编码。 不要像这样在循环中连接字符串-使用StringBuilder。 您正在忽略InputStream.Read的返回值。在阅读ByteArrayInputStream时,这可能没什么问题,但您通常不应该依赖它。 每次都会创建一个新的Random实例。我相信这在Java6中是可以的,但是在早期版本中会给您重复的值。基本上,这是个坏主意。重复使用Random的一个实例。
嗯,这里有几个问题:

您正在对字符串使用默认的平台编码。不要那样做。指定要在字节和文本之间转换的特定字符串编码。 不要像这样在循环中连接字符串-使用StringBuilder。 您正在忽略InputStream.Read的返回值。在阅读ByteArrayInputStream时,这可能没什么问题,但您通常不应该依赖它。 每次都会创建一个新的Random实例。我相信这在Java6中是可以的,但是在早期版本中会给您重复的值。基本上,这是个坏主意。重复使用Random的一个实例。 我认为所需的CPU时间应该根据数组大小线性增加,但基准测试程序显示,处理30000字节所需的时间比处理3000字节所需的时间多得多

事实上,我希望它会随着阵列的大小呈二次增长。如果要分析该程序,您可能会发现大部分时间都在调用String.concat。随着阵列变大,比例也会增加

基本上,每次进行字符串连接时,都会将迄今为止积累的所有字符复制到一个新字符串中。。。扔掉前一个。不难看出代码的这一部分在**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();
我认为所需的CPU时间应该根据数组大小线性增加,但基准测试程序显示,处理30000字节所需的时间比处理3000字节所需的时间多得多

事实上,我希望它会随着阵列的大小呈二次增长。如果要分析该程序,您可能会发现大部分时间都在调用String.concat。随着阵列变大,比例也会增加

基本上,每次进行字符串连接时,都会将迄今为止积累的所有字符复制到一个新字符串中。。。扔掉前一个。不难看出代码的这一部分在**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();

为什么您认为需要增加缓冲区大小,因为数据大小会增加?事实并非如此。

为什么您认为需要增加缓冲区大小,因为数据大小会增加?事实并非如此。

可能使用stringbuilder?可能使用stringbuilder?他在每次调用getNextRandom时都创建一个新的随机对象,在每次调用getNextRandom时都创建一个新的随机对象