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
- 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>, 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: Sat, 03 Jan 2004 22:32:35 -0600
- Subject: [PATCH] for Review: BufferedReader and InputStreamReader Optimizations
- Reply-to: gnustuff at thisiscool dot com
Hi People,
No one has stepped forward with an alternative to this yet:
http://gcc.gnu.org/ml/java/2003-12/msg00208.html
...so I'm officially submitting a patch for this with the change to the
native BufferedReader.lineEnd() as per this:
http://gcc.gnu.org/ml/java/2003-12/msg00213.html
I ran this through a full "make check" in libjava for i686-pc-linux-gnu,
including the Mauve tests (thanks to Andreas Tobler for teaching me
how to do this) and the pre-patch and post-patch results are basically
the same. (The pre-patch testsuite log prints a GC warning about
repeated allocation of a very large block, but I can't imagine this
being related.)
What do you all think?
-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/
ChangeLog
2004-01-03 Mohan Embar <gnustuff@thisiscool.com>
* Makefile.am (nat_source_files): Added java/io/natBufferedReader.cc.
* Makefile.in: Rebuilt.
* java/io/BufferedReader.java (sbuf): New field.
(lineEnd): Removed implementation and changed to native declaration.
(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.
* java/io/natBufferedReader.cc (lineEnd): Native implementation
for BufferedReader.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.350
diff -u -2 -r1.350 Makefile.am
--- Makefile.am 31 Dec 2003 08:58:29 -0000 1.350
+++ Makefile.am 4 Jan 2004 01:34:32 -0000
@@ -2759,4 +2759,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.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 4 Jan 2004 01:35:08 -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.
@@ -399,15 +404,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);
/**
@@ -440,5 +435,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 +446,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 4 Jan 2004 01:35:09 -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 2004-01-03 19:54:04.000000000 -0600
+++ java/io/natBufferedReader.cc 2004-01-03 22:46:07.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 BufferedReader "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);
+ int i = pos;
+ for (; i < limit; i++)
+ {
+ jchar ch = pbuf[i];
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ return i;
+}