执行时间:Iterativ与实例

时间:2019-03-24 01:01:47

标签: java execution-time

在用Java编码时,我偶然发现了一件奇怪的事情:

我将文件读入字节数组(byte[] file_bytes)中,我想要的是十六进制转储输出(例如Linux中的实用程序hexdumpxxd)。基本上,这是可行的(请参见注释掉的for循环代码),但是对于较大的文件(> 100 KiB),需要一些时间来遍历bytearray块,进行正确的格式化,依此类推。

但是,如果我将for-loop-code替换为 注释掉的代码(使用具有相同for-loop-code的类进行计算!),它的工作速度非常快。 / p>

此行为的原因是什么?

代码段:

    [...]

    long counter = 1;
    int chunk_size = 512;
    int chunk_count = (int) Math.ceil((double) file_bytes.length / chunk_size);
    for (int i = 0; i < chunk_count; i++) {
        byte[] chunk = Arrays.copyOfRange(file_bytes, i * chunk_size, (i + 1) * chunk_size);

       // this commented two lines calculate way more faster than the for loop below, even though the calculation algorithm is the same!
       /* 
        * String test = new BytesToHexstring(chunk).getHexstring();
        * hex_string = hex_string.concat(test);
        */ 

        for (byte b : chunk) {
            if( (counter % 4) != 0 ){
                hex_string = hex_string.concat(String.format("%02X ", b));
            } else{
                hex_string = hex_string.concat(String.format("%02X\n", b)); 
            }
            counter++;
        }
    }

    [...]

BytesToHexstring类:

class BytesToHexstring {
    private String m_hexstring;

    public BytesToHexstringTask(byte[] ba) {
        m_hexstring = "";
        m_hexstring = bytes_to_hex_string(ba);
    }

    private String bytes_to_hex_string(byte[] ba) {
        String hexstring = "";
        int counter = 1;

        // same calculation algorithm like in the codesnippet above!
        for (byte b : ba) {
            if ((counter % 4) != 0) {
                hexstring = hexstring.concat(String.format("%02X ", b));
            } else {
                hexstring = hexstring.concat(String.format("%02X\n", b));
            }
            counter++;
        }
        return hexstring;
    }

    public String getHexstring() {
        return m_hexstring;
    }

}

字符串hex_string:

00 11 22 33
44 55 66 77
88 99 AA BB
CC DD EE FF

基准:

  1. file_bytes.length = 102400字节= 100 KiB

    • 通过课程:〜0.7秒
    • 不上课:〜5,2秒
  2. file_bytes.length = 256000字节= 250 KiB

    • 通过课程:〜1,2秒
    • 不上课:〜36秒

1 个答案:

答案 0 :(得分:2)

两个选项之间有一个重要区别。在慢速版本中,您将每次迭代连接到为每个字节建立的整个十六进制字符串上。字符串连接是一个缓慢的操作,因为它需要复制整个字符串。当字符串变大时,此复制将花费更长的时间,并且每个字节都会复制整个内容。

在更快的版本中,您将分别构建每个块,并且仅将整个块与输出字符串而不是每个单独的字节连接在一起。这意味着昂贵的串联要少得多。在构建uyp块时,您仍在使用串联,但是由于块比整个输出小得多,因此这些串联更快。

尽管通过使用字符串生成器而不是字符串连接,您可以做得更好。 StringBuilder是一个用于高效地逐步构建字符串的类。它避免了串联所做的每个追加上的完整副本。我希望如果将其重新构造为使用StringBuilder,则两个版本的性能大致相同,并且比您已经拥有的两个版本都要快。