2831

I generated two matrices of 1000 x 1000:

First Matrix: O and #.
Second Matrix: O and B.

Using the following code, the first matrix took 8.52 seconds to complete:

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("");
 }

With this code, the second matrix took 259.152 seconds to complete:

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("");
}

What is the reason behind the dramatically different run times?


As suggested in the comments, printing only System.out.print("#"); takes 7.8871 seconds, whereas System.out.print("B"); gives still printing....

As others who pointed out that it works for them normally, I tried Ideone.com for instance, and both pieces of code execute at the same speed.

Test Conditions:

  • I ran this test from Netbeans 7.2, with the output into its console
  • I used System.nanoTime() for measurements
cнŝdk
  • 28,676
  • 7
  • 47
  • 67
Kuba Spatny
  • 24,958
  • 9
  • 33
  • 58
  • 62
    Try changing rand.nextInt(4) == 0 to i < 250 to eliminate the effect of the random generator. You might run out of entropy that slows down the random generation – fejese Feb 21 '14 at 23:49
  • 3
    Both seem to run for same amount of time on my machine, ~4 seconds. – Sotirios Delimanolis Feb 21 '14 at 23:51
  • 3
    @fejese Then [branch prediction](http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array/11227902#11227902) would kick in. Something like changing `rand.nextInt(4)==0` to `i%4==0` would be better (in terms of avoiding branch prediction speeding up the process) – Justin Feb 21 '14 at 23:52
  • 161
    if you are suggesting that printing B takes more time than printing #....why dont you try to print all B & all # rather than relying on random variable r – Kakarot Feb 21 '14 at 23:52
  • 2
    Across three trials of each ('B' vs '#') I'm getting between 36 and 38 seconds (rounded down). I added startTime and endTime fields that grab System.currentTimeMillis before and after the loop for my timing. I'm going to suggest that there's some problem local to you (runtime engine, processor, black helicopters). – MarsAtomic Feb 21 '14 at 23:59
  • 19
    Based on the accepted answer, you apparently didn't try running it with output redirected to a file or /dev/null. – Barmar Feb 23 '14 at 03:21
  • 26
    @fejese, Random() is not a cryptographical rng and so doesn't use up the entropy pool. – Divide Feb 25 '14 at 11:44
  • [tag:matrix], @FrancescoMenzani? IMO it makes no sense here; is makes the question not a bit easier to find, does not describe its scope better, just adds noise. – Palec Aug 31 '15 at 17:40
  • 1
    @Palec I couldn't find any print tag specific to `System.out`, but I think [tag:system.out] itself will represent that part of the question quite good. – sponge Sep 01 '15 at 13:10
  • I tried running the same code on my system. In each of the 20 trials, printing "#" code was 3-5 times *SLOWER* than printing "B". – Nishit Apr 05 '18 at 04:14

3 Answers3

4151

Pure speculation is that you're using a terminal that attempts to do word-wrapping rather than character-wrapping, and treats B as a word character but # as a non-word character. So when it reaches the end of a line and searches for a place to break the line, it sees a # almost immediately and happily breaks there; whereas with the B, it has to keep searching for longer, and may have more text to wrap (which may be expensive on some terminals, e.g., outputting backspaces, then outputting spaces to overwrite the letters being wrapped).

But that's pure speculation.

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • 325
    Brilliant deduction. But we should generalize from this lesson, and always measure performance with output either eliminated, directed to /dev/null (NUL on Windows) or at least to a file. Displaying on any sort of Console is generally very expensive IO, and always distorts timings -- even if not as dramatically confusingly as this. – Bob Kerns Feb 23 '14 at 22:38
  • 18
    @BobKerns: Surely that would still have generated an appropriate question though. The problem remains that printing Bs takes longer and not printing them isn't really a solution so much as a trick to help debug the problem. – Chris Feb 24 '14 at 15:09
  • 2
    Is this still speculation? I mean, does System.out.print actually do word wrapping? Do we have documentation somewhere? Can you switch this feature on and off? – Mr Lister Feb 26 '14 at 20:22
  • 7
    @MrLister this is not an issue with System.out, but with its consumer, in this case NetBeans' console view. Whether you can turn it off, check in Netbeans' settings. – Silly Freak Feb 26 '14 at 20:35
  • 40
    @MrLister: `System.out.println` doesn't do wordwrapping; the thing it was outputting to was doing word-wrapping (and blocking, so `System.out.println` had to wait). – T.J. Crowder Feb 26 '14 at 22:11
  • 41
    @Chris -- actually, I'll argue that not printing them IS the solution, to the problem of getting accurate timings of the algorithm. Each time you print to a Console (of any sort), you're invoking all manner of external processing not related to what you're testing the performance of. That's a bug in your measurement procedure, pure and simple. On the other hand, if you view the problem not as measurement, but understanding the discrepancy, then yes, not printing is a debugging trick. It comes down to, which problem are you trying to solve? – Bob Kerns Mar 03 '14 at 12:27
  • 11
    @BobKerns Thanks for injecting some sanity into this thread! So many people don't seem to understand this. You need to be careful that you are **only measuring the thing you are trying to measure** – UpAndAdam Apr 04 '14 at 20:11
  • @SillyFreak Can you please tell me what is meant by "word wrapping must be done in case of B" ? – Koray Tugay Jan 11 '15 at 16:52
  • 1
    @KorayTugay where do you have that quote from? Word wrapping apparently *is* done, and that's the *problem*, if you want to view it as such. It's nothing that "must be done" to fix anything relating to this question. – Silly Freak Jan 11 '15 at 20:34
  • 7
    IO is crazy expensive. We once needed to write to a DB random data. The guy who originally wrote the code put printf("%s\r",lineCount); for all iterations. 1 million entries did not finish in 24 hours. I simply put a if(lineCount % 1000 ==) and it finished within 30 seconds. – Christian Bongiorno Jan 14 '15 at 16:59
  • Eclipse, NetBeans, less, gedit and emacs all have major performance issues with long lines. Somehow they managed to write code that runs as something like O(N^2) in the length of the line. This is a common, dumb problem that really needs to be solved in all these programs. – Luke Hutchison Mar 11 '18 at 04:36
  • 1
    I noticed many years ago how applications printing a lot of things to the console can run a lot faster when minimized, so I figured the output stream is a blocking operation, but never would have thought the other side of the stream (in this case, the shell) would have a hard time keeping up taking stuff out of the stream. Great catch, great answer. I wonder if these terminals should add multithreading for reducing the time blocking the streams. – cleberz Oct 04 '18 at 21:42
  • 1
    @cleberz there's a number of processes I run from Command that I always run in minimized or tiny windows because they finish much, much more quickly that way. – GoatInTheMachine Oct 23 '18 at 13:55
228

I performed tests on Eclipse vs Netbeans 8.0.2, both with Java version 1.8; I used System.nanoTime() for measurements.

Eclipse:

I got the same time on both cases - around 1.564 seconds.

Netbeans:

  • Using "#": 1.536 seconds
  • Using "B": 44.164 seconds

So, it looks like Netbeans has bad performance on print to console.

After more research I realized that the problem is line-wrapping of the max buffer of Netbeans (it's not restricted to System.out.println command), demonstrated by this code:

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("");
}

The time results are less then 1 millisecond every iteration except every fifth iteration, when the time result is around 225 millisecond. Something like (in nanoseconds):

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

And so on..

Summary:

  1. Eclipse works perfectly with "B"
  2. Netbeans has a line-wrapping problem that can be solved (because the problem does not occur in eclipse)(without adding space after B ("B ")).
Community
  • 1
  • 1
Roy Shmuli
  • 4,489
  • 1
  • 21
  • 38
16

Yes the culprit is definitely word-wrapping. When I tested your two programs, NetBeans IDE 8.2 gave me the following result.

  1. First Matrix: O and # = 6.03 seconds
  2. Second Matrix: O and B = 50.97 seconds

Looking at your code closely you have used a line break at the end of first loop. But you didn't use any line break in second loop. So you are going to print a word with 1000 characters in the second loop. That causes a word-wrapping problem. If we use a non-word character " " after B, it takes only 5.35 seconds to compile the program. And If we use a line break in the second loop after passing 100 values or 50 values, it takes only 8.56 seconds and 7.05 seconds respectively.

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");
        }
        if(j%100==0){               //Adding a line break in second loop      
            System.out.println();
        }                    
    }
    System.out.println("");                
}

Another advice is that to change settings of NetBeans IDE. First of all, go to NetBeans Tools and click Options. After that click Editor and go to Formatting tab. Then select Anywhere in Line Wrap Option. It will take almost 6.24% less time to compile the program.

NetBeans Editor Settings

ROOT
  • 10,339
  • 5
  • 24
  • 40
Abdul Alim Shakir
  • 821
  • 11
  • 22
  • 1
    "It will take almost 6.24% less time to compile the program." surely you refer to executing, not compiling... – eis Jan 17 '21 at 17:14