Re: Why is Java so slow????
Bent C Dalager wrote:
From reading PrintStream's javadoc, what the wrapping PrintStream
ought to be doing is handle its own buffer and its own (absence of)
autoflush so that whatever data goes through to the wrapped one comes
in much larger chunks. That the wrapped one then autoflushes these
large chunks shouldn't really matter.
Right. The new PrintStream doesn't autoflush. But the old one that it
wraps does. I don't think a PrintStream does any buffering itself, so
the first PrintStream will just pass the writes down to the the wrapped
PrintStream, which will do auto-flushes.
Set this up in an IDE and then run it with the debugger. Poke the
internal variables (especially the inherited one "out") and you'll see.
It's actually quite simple and un-mystical.
Of course, this may not actually be what happens :-)
Why is wrapping with a second BufferedOutputStream so much faster? I
dunno, but I'm guessing it does buffer, and it does cut down the calls
to PrintStream. PrintStream will still autoflush though, just perhaps
less often.
The problem is that System.out's PrintStream autoflushes most things,
so the trick would be to wrap it into something that does /not/
autoflush but waits until some reasonably-sized buffer is full before
passing it on. My assumption was that a default PrintStream would do
this because it says that it defaults to not auto-flushing. A wrapping
BufferedOutputStream would basically do the same thing.
Yes. Somewhere above there's a discussion on using the FileDescriptors,
which I didn't know where available.
PrintStream System.out = new PrintStream( new BufferedOutputStream(
FileDescriptor.out), true );
This is how I think the System.out variable gets set up. Obviously you
can do the same thing with FileDescriptor.out just setting the auto
flush parameter to false.
However testing this, for me the above code (with auto-flush set to
false) was a tad slower than:
BufferedOutputStream os = new BufferedOutputStream( System.out );
I don't know why this is. Possibly the JVM is doing some optimization
tricks on it's own PrintStream to make it faster. So using the special
optimized one is faster than double buffering all IO. Or it could be
bad testing on my part, other random factors, etc. Not really sure.
Also important to remember: println() is very, very slow. print() is a
little faster, even when printing newlines and with autoflush enabled.
All versions of write() are much faster by almost an order of magnitude,
and the fastest still is the three argument version, in some cases by a
factor of 2x over the other write()'s. I'm not sure why, but I think it
may have to do with virtual method overhead.
That's my one nickel summary of what's been discussed here.