|
Description
|
Subject: changes to java.io.RandomAccessFile.readUnsignedShort()
Date: Wed, 26 Aug 1998 21:45:35 -0400
The following program produces different results when run with the JDK
1.2 beta4 and the JDK 1.2 beta4.1. The reason is because of the
(presumably) performance enhancement made to
java.io.RandomAccessFile.readUnsignedShort() whereby it calls
readTwoBytes(), a native method instead of sequential calls to read().
Changing the internal implementation of java.io.RandomAccessFile is
probably well within your rights. I will grant you that it was never
part of the published contract of java.io.RandomAccessFile that
readByte, readShort, readInt, etc. would necessarily use one of the
three overloadings of read() to gather their bytes, but one might
have surmised this from the following facts:
(1) java.io.RandomAccessFile was/is not a final class and is therefore
meant to be extended,
(2) readByte, readShort, readInt, etc. are declared to be final
methods, and
(3) read(), read(byte[]), and read(byte[], int, int) are not declared
to be final methods meaning that they are allowed to be extended.
The example below is admittedly contrived, but we do in fact extend
RandomAccessFile in ObjectStore PSE (used by JINI's ObjectSpaces) to
provide buffering on top of RandomAccessFile. Yes, I can recode this
so that I provide my own implementations of readFully, readByte,
readInt, readShort, and readUTF, but I can't make strict overloadings
of the method signatures declared for RandomAccessFile (since they're
final).
It also means we'll have to ship a new release of PSE in order to have
it work with the JDK 1.2 beta 4.1.
So, is there some really good performance improvement that comes with
this change from read(), read() to readTwoBytes() (ditto for
writeUnsignedShort())?
Thanks for your comments on this.
import java.io.*;
public class ReadOT {
class ExtendedRAF extends java.io.RandomAccessFile {
ExtendedRAF(String name, String mode) throws IOException {
super(name, mode);
}
private byte[] rb = new byte[1];
public int read() throws IOException {
System.out.println("ERAF read() called");
int ret = read(rb, 0, 1);
if (ret < 0)
return -1;
else
return (rb[0] & 0xff);
}
public int read(byte[] b, int off, int len) throws IOException {
System.out.println("ERAF read(byte[], int, int) called");
return super.read(b, off, len);
}
public int read(byte b[]) throws IOException {
System.out.println("ERAF read(byte[]) called");
return read(b, 0, b.length);
}
}
static public void main(String argv[]) throws IOException {
ReadOT rot = new ReadOT();
ExtendedRAF eraf = rot.new ExtendedRAF("foo", "rw");
eraf.writeShort(123);
eraf.seek(0);
System.out.println(eraf.readShort());
}
}
|
|
Evaluation
|
The performance improvements obtained by the recent changes to RandomAccessFile
were significant. For the record, here are some timings:
Solaris 2.6 Windows NT 4.0
166MHz Ultra-1 266MHz Pentium-II
old new old new
writeLong 9540 1435 3135 441
writeInt 4790 1316 1682 451
writeChar 2485 1275 842 481
writeShort 2422 1276 841 471
readInt 4435 1114 1592 371
readChar 2263 1156 771 430
readUnsignedShort 2258 1178 791 410
readShort 2259 1169 771 401
Each line measures the time, in milliseconds, required to invoke the named
method 50000 times against an existing 400000-byte file. With the new native
methods the times change very little with the length of the data type being
written, while with the old pure Java code the times are directly proportional
to the length.
Despite these improvements, compatibility dictates that these optimizations be
backed out. The original suggestion in RFE 4137835 was to reduce the number of
kernel calls by creating small temporary byte arrays. We did not adopt that
approach because it can lead to vastly increased object-allocation rates. If
we were to adopt that approach now, it would not work very well with the
buffered RandomAccessFile subclass described in this bug report either.
Developers can achieve better performance by buffering data themselves, either
by subclassing RandomAccessFile or by buffering data before invoking the methods
of a RandomAccessFile object. Therefore it's probably best to close 4137835 as
"will not fix," and address random-access file performance with a new class in
a future feature release.
-- xxxxx@xxxxx 8/31/1998
|