This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[PATCH] for Review: BufferedReader and InputStreamReader Optimizations (Updated)
- From: Mohan Embar <gnustuff at thisiscool dot com>
- To: GCJ Patches <java-patches at gcc dot gnu dot org>
- Cc: Bryce McKinlay <bryce at mckinlay dot net dot nz>, tromey at redhat dot com, per at bothner dot net
- Date: Thu, 29 Jan 2004 21:55:44 -0600
- Subject: [PATCH] for Review: BufferedReader and InputStreamReader Optimizations (Updated)
- Reply-to: gnustuff at thisiscool dot com
Hi People,
Knock knock. It's me again, with the >50% improvement for
BufferedReader.readline():
BEFORE:
running gcj version
100000
real 0m35.892s
user 0m33.416s
sys 0m1.400s
running jdk version
100000
real 0m17.067s
user 0m15.590s
sys 0m1.088s
AFTER:
running gcj version
100000
real 0m19.490s
user 0m16.068s
sys 0m1.316s
running jdk version
100000
real 0m17.285s
user 0m15.676s
sys 0m1.125s
(
The above test is here:
http://gcc.gnu.org/ml/java/2003-12/msg00021.html
)
Bryce and I spoke off-list about my original submission:
http://gcc.gnu.org/ml/java-patches/2004-q1/msg00008.html
...and he pointed out that it might be controversial to
introduce a native method for BufferedReader purely for
a small speed improvement. Although removing this makes
Sun's JRE win over gcj, I'm willing to live with this
compromise and I removed the native method from this
updated patch, which is against the trunk.
Bryce said off-list that we should consider a combination
of his efforts:
http://gcc.gnu.org/ml/java/2004-01/msg00029.html
...and mine. I would love for this to happen, but given
that there were possible issues with Bryce's initial attempt:
http://gcc.gnu.org/ml/java/2004-01/msg00035.html
...my recommendation would be to check my version in,
enjoy the immediate performance gain, then let Bryce, Dalibor
or whoever else tear this to pieces if he is so inclined.
-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/
ChangeLog
2004-01-29 Mohan Embar <gnustuff@thisiscool.com>
* java/io/BufferedReader.java (sbuf): New field.
(readLine): Use String.valueOf instead of new String() as per
Per Bothner's suggestion. Use instance sbuf field instead of a
local StringBuffer instance.
* java/io/InputStreamReader.java (read(char[],int,int)): Pass the
caller's buffer to refill().
(read(void)): Pass our internal work buffer to refill if our
input queue is empty.
(refill): Changed return type to int. Use the specified buffer
instead of our work buffer as per Bryce McKinlay's suggestion.
Return the number of characters read or -1 for EOF.
Index: java/io/BufferedReader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/BufferedReader.java,v
retrieving revision 1.16
diff -u -2 -r1.16 BufferedReader.java
--- java/io/BufferedReader.java 28 Dec 2003 11:54:17 -0000 1.16
+++ java/io/BufferedReader.java 30 Jan 2004 03:36:35 -0000
@@ -90,4 +90,9 @@
/**
+ * The line buffer for <code>readLine</code>.
+ */
+ private StringBuffer sbuf = null;
+
+ /**
* Create a new <code>BufferedReader</code> that will read from the
* specified subordinate stream with a default buffer size of 8192 chars.
@@ -440,5 +445,5 @@
if (i < limit)
{
- String str = new String(buffer, pos, i - pos);
+ String str = String.valueOf(buffer, pos, i - pos);
pos = i + 1;
// If the last char in the buffer is a '\r', we must remember
@@ -451,5 +456,8 @@
return str;
}
- StringBuffer sbuf = new StringBuffer(200);
+ if (sbuf == null)
+ sbuf = new StringBuffer(200);
+ else
+ sbuf.setLength(0);
sbuf.append(buffer, pos, i - pos);
pos = i;
Index: java/io/InputStreamReader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/InputStreamReader.java,v
retrieving revision 1.15
diff -u -2 -r1.15 InputStreamReader.java
--- java/io/InputStreamReader.java 9 May 2003 07:10:58 -0000 1.15
+++ java/io/InputStreamReader.java 30 Jan 2004 03:36:35 -0000
@@ -232,8 +232,6 @@
if (wavail <= 0)
{
- // Nothing waiting, so refill our buffer.
- if (! refill ())
- return -1;
- wavail = wcount - wpos;
+ // Nothing waiting, so refill their buffer.
+ return refill(buf, offset, length);
}
@@ -263,7 +261,12 @@
if (wavail <= 0)
{
- // Nothing waiting, so refill our buffer.
- if (! refill ())
+ // Nothing waiting, so refill our internal buffer.
+ wpos = wcount = 0;
+ if (work == null)
+ work = new char[100];
+ int count = refill(work, 0, work.length);
+ if (count == -1)
return -1;
+ wcount += count;
}
@@ -272,13 +275,8 @@
}
- // Read more bytes and convert them into the WORK buffer.
- // Return false on EOF.
- private boolean refill () throws IOException
+ // Read more bytes and convert them into the specified buffer.
+ // Returns the number of converted characters or -1 on EOF.
+ private int refill(char[] buf, int offset, int length) throws IOException
{
- wcount = wpos = 0;
-
- if (work == null)
- work = new char[100];
-
for (;;)
{
@@ -291,16 +289,12 @@
in.reset ();
if (! r)
- return false;
+ return -1;
converter.setInput(in.buf, in.pos, in.count);
- int count = converter.read (work, wpos, work.length - wpos);
+ int count = converter.read(buf, offset, length);
in.skip(converter.inpos - in.pos);
if (count > 0)
- {
- wcount += count;
- return true;
- }
+ return count;
}
}
-
} // class InputStreamReader