题 为什么打印“B”比打印“#”要慢得多?


我生成了两个矩阵 1000 X 1000

第一矩阵: O 和 #
第二个矩阵: O 和 B

使用以下代码,第一个矩阵需要8.52秒才能完成:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("#");
        }
    }

   System.out.println("");
 }

使用此代码,第二个矩阵需要259.152秒才能完成:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B"); //only line changed
        }
    }

    System.out.println("");
}

运行时间大不相同的原因是什么?


正如评论中所建议的那样,仅打印 System.out.print("#"); 需要 7.8871 秒,而 System.out.print("B"); 给 still printing...

正如其他人指出它通常适合他们一样,我试过了 Ideone.com 例如,两段代码以相同的速度执行。

测试条件:

  • 我跑了这个测试 Netbeans 7.2,输出到其控制台
  • 我用了 System.nanoTime() 用于测量

2417
2018-02-21 23:45


起源


尝试将rand.nextInt(4)== 0更改为i <250,以消除随机生成器的影响。您可能会耗尽熵,从而减慢随机生成速度 - fejese
两者似乎在我的机器上运行相同的时间,约4秒。 - Sotirios Delimanolis
如果你建议打印B比打印花费更多时间#....为什么不尝试打印所有B&all#而不是依赖随机变量r - Kakarot
基于接受的答案,您显然没有尝试使用重定向到文件或/ dev / null的输出来运行它。 - Barmar
@fejese,Random()不是加密rng,因此不会耗尽熵池。 - Divide


答案:


纯粹的猜测 是你正在使用试图做的终端 自动换行 而不是字符包装和对待 B 作为一个单词字符,但 # 作为一个非单词字符。所以当它到达一条线的末端并搜索一个断线的地方时,它会看到一条线 # 几乎立刻,愉快地在那里打破;而与 B它必须继续搜索更长的时间,并且可能有更多的文本要包装(在某些终端上可能很昂贵,例如输出退格,然后输出空格来覆盖被包装的字母)。

但那是纯粹的猜测。


3721
2018-04-03 15:01



这实际上是正确的答案!之后添加空格 B 解决它。 - Kuba Spatny
有一些答案来自艰苦的学习经验。 T.J.而我(因为我们是朋友)在Apple [和zx80 /​​ 81]时代长大。那时没有内置的自动换行。所以我们最终都写了自己的 - 不止一次。那些课程坚持你,他们被焚烧到你的蜥蜴大脑。但是如果你在那之后倾向于代码,当你的环境词包装了所有东西,或者你在运行之前手动完成它时,就很难遇到自动换行的问题。 - JockM
精彩演绎。但是我们应该从这一课中概括,并始终测量性能,输出要么被消除,要么导致/ dev / null(Windows上的NUL)或者至少是文件。在任何类型的控制台上显示通常是非常昂贵的IO,并且总是会使时序失真 - 即使不像这样令人困惑。 - Bob Kerns
@MrLister: System.out.println 不做文字包装;它输出的东西是自动换行(和阻塞,所以 System.out.println 不得不等待)。 - T.J. Crowder
@Chris - 实际上,我认为不打印它们是解决问题的方法,也就是获得算法准确计时的问题。每次打印到控制台(任何类型)时,您都会调用与您正在测试其性能无关的所有外部处理方式。这是您测量过程中的一个错误,纯粹而简单。另一方面,如果您将问题视为不是测量,而是了解差异,那么是的,不打印是一种调试技巧。归结为,你试图解决哪个问题? - Bob Kerns


我在Eclipse vs Netbeans 8.0.2上进行了测试,两者都使用Java版本1.8; 我用了 System.nanoTime() 用于测量。

蚀:

我拿到 同时在两个案件上  - 周围 1.564秒

Netbeans的:

  • 使用“#”: 1.536秒
  • 使用“B”: 44.164秒

因此,看起来Netbeans在打印到控制台时表现不佳。

经过更多的研究,我意识到问题是 换行 Netbeans的最大缓冲区(它不限于 System.out.println 命令),由此代码演示:

for (int i = 0; i < 1000; i++) {
    long t1 = System.nanoTime();
    System.out.print("BBB......BBB"); \\<-contain 1000 "B"
    long t2 = System.nanoTime();
    System.out.println(t2-t1);
    System.out.println("");
}

除了每次迭代,时间结果小于1毫秒 每五次迭代,当时间结果大约是225毫秒。像(以纳秒为单位)的东西:

BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
.
.
.

等等..

概要:

  1. Eclipse与“B”完美配合
  2. Netbeans有一个可以解决的换行问题(因为在eclipse中不会出现问题)(在B(“B”)之后没有添加空格)。

148



你能详细说明你的研究策略,然后最终导致你发现线条缠绕是罪魁祸首吗? (我很好奇你的侦探技能,那就是!) - silph