Monday, May 26, 2008

Java Roadblock Part 2

I tried a test program:
RandomAccessFile f = new RandomAccessFile("tmp", "rw");
f.seek(3L * 1024 * 1024 * 1024);
f.write(123);
FileChannel channel = f.getChannel();
long size = channel.size();
System.out.println("File is " + size + " bytes large");
for (int i = 0; i < 10; ++i) {
long ofs = 0;
int chunksize = 512 * 1024 * 1024;
while (ofs < size) {
int n = (int)Math.min(chunksize, size - ofs);
int tries = 0;
ByteBuffer buffer = null;
do {
try {
buffer = channel.map(FileChannel.MapMode.READ_ONLY, ofs, n);
} catch (IOException e) {
if (++tries > 10)
throw e;
System.gc();
System.runFinalization();
}
} while (buffer == null);
System.out.println("Mapped " + n + " bytes at offset " + ofs +
" with " + tries + " tries");
ofs += n;
buffer = null; // "unmap"
}
}
channel.close();
It took 0 to 3 "tries" of forcing garbage collection and finalization. Of course, this is in the context of a simple test program. A large active heap might be better - because of frequent garbage collection - or it might be worse due to delayed finalization.

This might or might not be workable for Suneido. Currently I only map up to 1 gb at a time. That means by the time I might run out of address space there would be a lot of unreferenced mappings and hopefully at least some of them would get finalized.

This was on my Mac which I see is defaulting to Java 5 (although 6 is installed). On my work Windows machine with Java 6, I get 0 tries every time! Either it works better on Windows or it works better on Java 6. Hopefully the latter!

So I guess I'll forge ahead. I'll leave in the code to force garbage collection and finalization if the mapping fails since it doesn't hurt anything. I should probably log it somehow so I know if it's happening.

One thing I haven't quite figured out is how growing the file fits in with mapping. In my test program I had to actually "write" at the end of the file to allow mapping. This may differ between operating systems.

PS. The other "solution" is to use the 64 bit version of Java (on a 64 bit OS). Then there is no shortage of address space. I could even go back to the simpler approach of just mapping the whole file. (Although there are issues with that with growing the file.)

No comments: