This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: gcj's IO performance vs blackdown JDK
- From: Mohan Embar <gnustuff at thisiscool dot com>
- To: Bryce McKinlay <bryce at mckinlay dot net dot nz>
- Cc: Christopher Marshall <christopherlmarshall at yahoo dot com>, tromey at redhat dot com, per at bothner dot net, java at gcc dot gnu dot org
- Date: Fri, 26 Dec 2003 11:59:37 -0600
- Subject: Re: gcj's IO performance vs blackdown JDK
- Reply-to: gnustuff at thisiscool dot com
Hi Bryce,
>...Solution: fix InputSreamReader to decode characters directly into the
>array given to it in the read() method. This brought us up to about 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.
>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.
I was too eager to try this out to wait 'til next week :)
Here are my timings for successive iterations of this. And attached is
my informal patch for the (direct read into buffer + StringBuffer member
variable + String.valueOf() + lineEnd() native) fix.
I am going to stop here and leave this alone unless someone wants me
to follow up on this.
I also eliminated the unnecessary synchronization, but judged the
time savings too insignificant to be worthy of inclusion. If anyone
wants the code, let me know.
-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/
current CVS version
-------------------
running gcj version
100000
real 0m34.864s
user 0m33.148s
sys 0m1.369s
running jdk version
100000
real 0m17.047s
user 0m15.639s
sys 0m1.020s
direct read into buffer
-------------------
running gcj version
100000
real 0m18.608s
user 0m16.908s
sys 0m1.326s
running jdk version
100000
real 0m17.430s
user 0m15.600s
sys 0m1.051s
direct read into buffer
+ StringBuffer member variable
-------------------
running gcj version
100000
real 0m18.009s
user 0m16.227s
sys 0m1.361s
running jdk version
100000
real 0m16.970s
user 0m15.633s
sys 0m1.010s
direct read into buffer
+ StringBuffer member variable
+ String.valueOf()
-------------------
running gcj version
100000
real 0m17.868s
user 0m16.033s
sys 0m1.410s
running jdk version
100000
real 0m17.314s
user 0m15.613s
sys 0m1.164s
direct read into buffer
+ StringBuffer member variable
+ String.valueOf()
+ lineEnd() native
-------------------
running gcj version
100000
real 0m17.185s
user 0m15.412s
sys 0m1.330s
running jdk version
100000
real 0m17.001s
user 0m15.615s
sys 0m1.027s
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.347
diff -u -2 -r1.347 Makefile.am
--- Makefile.am 23 Dec 2003 11:55:29 -0000 1.347
+++ Makefile.am 26 Dec 2003 17:43:13 -0000
@@ -2739,4 +2739,5 @@
gnu/java/nio/natSelectorImpl.cc \
gnu/java/nio/natNIOServerSocket.cc \
+java/io/natBufferedReader.cc \
java/io/natFile.cc \
java/io/natFileDescriptor.cc \
Index: java/io/BufferedReader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/BufferedReader.java,v
retrieving revision 1.14
diff -u -2 -r1.14 BufferedReader.java
--- java/io/BufferedReader.java 14 Jun 2003 05:44:38 -0000 1.14
+++ java/io/BufferedReader.java 26 Dec 2003 17:43:33 -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.
@@ -389,15 +394,5 @@
* if no line terminators were found.
*/
- private int lineEnd(int limit)
- {
- int i = pos;
- for (; i < limit; i++)
- {
- char ch = buffer[i];
- if (ch == '\n' || ch == '\r')
- break;
- }
- return i;
- }
+ private native int lineEnd(int limit);
/**
@@ -430,5 +425,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
@@ -441,5 +436,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 26 Dec 2003 17:43:34 -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
Index: java/io/natBufferedReader.cc
===================================================================
--- java/io/natBufferedReader.cc 2003-12-26 12:02:29.000000000 -0600
+++ java/io/natBufferedReader.cc 2003-12-26 10:26:14.000000000 -0600
@@ -0,0 +1,29 @@
+// natBufferedReader.cc - Native part of BufferedReader class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
+
+ This ObjectInputStream is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the ObjectInputStream "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/io/BufferedReader.h>
+
+jint java::io::BufferedReader::lineEnd (jint limit)
+{
+ jchar *pbuf = elements (buffer) + pos;
+ int i = pos;
+ for (; i < limit; i++)
+ {
+ jchar ch = *pbuf++;
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ return i;
+}