Name: wm7046 Date: 07/08/2002
FULL PRODUCT VERSION :
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
FULL OPERATING SYSTEM VERSION : Any Windows, but tested
only on XP
A DESCRIPTION OF THE PROBLEM :
The 1.4 JDK introduces a new "synchronous write" mode flags
that can be specified in the java.io.RandomAccessFile
constructor. This essentially is intended to open the file
in the equivalent of Solaris' "O_SYNC" and "O_DSYNC" modes.
These flags are apparently totally ignored on Windows XP,
and likely all other versions of Windows.
Please give this bug a high priority as there is no
easy or similarly performing work-around. Also, this is a
"silent" bug, it is not detectable except by those that know
what the performance characteristics should be. Also, this
but is a "very bad thing" for data integrity.
------------------------------------------------------------
THE FIX:
The Sun JDK apparently uses the Windows POSIX library for
file I/O. Unfortunately, this library doesn't support
synchronous writes (i.e. O_SYNC or O_DSYNC), but I'm not
100% sure on this. A fix may require use of the non-POSIX
Win32 "CreateFile" function to open the file with the Win32
flag "FILE_FLAG_WRITE_THROUGH".
At BEA I have written native code that does just this, it
was this work that led me to the JDK1.4 bug...
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided sample code on java 1.4 on Windows:
"java TooFast"
Note that on Windows, unlike Solaris, the on-hard-drive
write-cache is enabled even for synchronous writes, unlike
Solaris. The test failure above may require disabling this
cache to recreate, to do this:
control panel
administrative tools
computer management
device manager
disk drives
click on your hard-drive
policies tab
uncheck "enable write caching on disk"
EXPECTED VERSUS ACTUAL BEHAVIOR :
On my Windows XP laptop 5400 RPM IDE hard-drive, the result
was:
<src_jms fileio/test> java TooFast
83333.24723782427 synchronous-writes/sec
Exception in thread "main" java.io.IOException: WAY WAY WAY
TOO FAST,
more than 5000 sync writes/sec,
Expect lower than 1000 writes per second
- (usually much lower).
at TooFast.main(TooFast.java:29)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.*;
/**
* Show something is wrong with JDK1.4 synchronous writes on Windows.
*/
public class TooFast {
public static void main(String [] args) throws Exception {
int NUMWRITES = 5000;
RandomAccessFile f;
Random r = new Random();
File file = new File("TooFast.out");
if (file.exists()) file.delete();
f = new RandomAccessFile(file,"rwd");
double before = (double)System.currentTimeMillis()/1000.0;
for (int i = NUMWRITES; i > 0; i--) {
f.seek(r.nextInt(100000));
f.write(new byte[1000]);
}
double after = (double)System.currentTimeMillis()/1000.0;
double writesPerSec = (NUMWRITES / (after - before));
System.out.println("\n" + writesPerSec + " synchronous-writes/sec\n");
if (writesPerSec > 5000)
throw new IOException("WAY WAY WAY TOO FAST,\n "
+ " more than 5000 sync writes/sec,\n "
+ " Expect lower than 1000 writes per second\n "
+ " - (usually much lower).");
System.out.println();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Modify application to call fd.sync() after each write() - a
huge performance hit. Alternatively, write your own native
code, which BEA has already done.
(Review ID: 158582)
======================================================================