gcj's IO performance vs blackdown JDK

Bryce McKinlay bryce@mckinlay.net.nz
Wed Dec 24 14:07:00 GMT 2003


On Dec 24, 2003, at 3:36 PM, Mohan Embar wrote:

>> Thanks Christopher, this is a useful test case. I suspect the problem
>> here is our horribly inefficient implementation of
>> BufferedReader.readLine(). Given that it is calling a synchronized
>> read() method in a loop for every character in the stream, I'm
>> surprised its only 3x slower! You might like to have a go at making a
>> more efficient implementation, or alternatively, file an "RFE" bug in
>> bugzilla.
>
> This has gone unclaimed for awhile, so I started messing around with 
> it.
>
> Actually, the problem isn't with the read() method. Although the call
> to it is synchronized, it gets called once and then the entire filled
> contents of the buffer are used.
>
> In the code below, I got rid of the synchronization, but the major gain
> came from reusing the StringBuffer throughout the lifetime of the 
> BufferedReader
> instance. This got me from 33s to 23s on my P450/256M. (The JRE time 
> is 15s.)
> I'm able to get an additional 2s gain (10%) by implementing lineEnd() 
> in CNI,
> thereby presumably avoiding the bounds checking.

Interesting. I actually already rewrote much of BufferedReader (based 
partly on the BufferedInputStream code) and got a small speed 
improvement (along with a big reduction in complexity), before 
realizing that the real performance problem was in InputStreamReader 
where the character conversion occurs. What was happening is that 
InputStreamReader was converting characters into a small internal 
buffer (only 100 chars IIRC), so when BufferedReader called read() on 
the InputStreamReader it only got a fraction of the amount of data 
needed to fill up its buffer. This also meant that there was an extra 
unnecessary layer of copying going on. Solution: fix InputSreamReader 
to decode characters directly into the array given to it in the read() 
method. This brought us up to about equal or slightly faster than the 
JRE 1.4.2 on Chris's test.

 From memory, my readLine() implementation only creates a StringBuffer 
in the event that the line crosses a boundary between buffers (ie the 
StringBuffer is used to store the start of a line when the buffer needs 
to be refilled), so given a full 8192 char buffer, the need to create a 
StringBuffer should be rare at least for input with "normal" sized 
lines.

I didn't get around to submitting this yet due partly to lack of time 
and partly because, being a significant code change and not fixing a 
bug, it isn't really suitable to commit before 3.4 branches. 
Unfortunately I don't have access to my development machine right now 
and I didn't think to grab a copy of my tree on my laptop, otherwise 
I'd post a copy. I'll post it next week.

Regards

Bryce.



More information about the Java mailing list