LUCENE-4740: Don't track clones of MMapIndexInput if unmapping is disabled. This reduces GC overhead.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1441726 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2013-02-02 10:35:54 +00:00
parent 722df2c1e7
commit 369f2379c2
3 changed files with 50 additions and 42 deletions

View File

@ -66,6 +66,9 @@ Optimizations
facets. Also added OrdinalPolicy.ALL_BUT_DIMENSION.
(Shai Erera, Michael McCandless)
* LUCENE-4740: Don't track clones of MMapIndexInput if unmapping
is disabled. This reduces GC overhead. (Kristofer Karlsson, Uwe Schindler)
New Features
* LUCENE-4686: New specialized DGapVInt8IntEncoder for facets (now the

View File

@ -51,14 +51,15 @@ abstract class ByteBufferIndexInput extends IndexInput {
private ByteBuffer curBuf; // redundant for speed: buffers[curBufIndex]
private boolean isClone = false;
private final WeakIdentityMap<ByteBufferIndexInput,Boolean> clones = WeakIdentityMap.newConcurrentHashMap();
private final WeakIdentityMap<ByteBufferIndexInput,Boolean> clones;
ByteBufferIndexInput(String resourceDescription, ByteBuffer[] buffers, long length, int chunkSizePower) throws IOException {
ByteBufferIndexInput(String resourceDescription, ByteBuffer[] buffers, long length, int chunkSizePower, boolean trackClones) throws IOException {
super(resourceDescription);
this.buffers = buffers;
this.length = length;
this.chunkSizePower = chunkSizePower;
this.chunkSizeMask = (1L << chunkSizePower) - 1L;
this.clones = trackClones ? WeakIdentityMap.<ByteBufferIndexInput,Boolean>newConcurrentHashMap() : null;
assert chunkSizePower >= 0 && chunkSizePower <= 30;
assert (length >>> chunkSizePower) < Integer.MAX_VALUE;
@ -231,7 +232,9 @@ abstract class ByteBufferIndexInput extends IndexInput {
clone.length = length;
// register the new clone in our clone list to clean it up on closing:
this.clones.put(clone, Boolean.TRUE);
if (clones != null) {
this.clones.put(clone, Boolean.TRUE);
}
return clone;
}
@ -272,17 +275,21 @@ abstract class ByteBufferIndexInput extends IndexInput {
// make local copy, then un-set early
final ByteBuffer[] bufs = buffers;
unsetBuffers();
clones.remove(this);
if (clones != null) {
clones.remove(this);
}
if (isClone) return;
// for extra safety unset also all clones' buffers:
for (Iterator<ByteBufferIndexInput> it = this.clones.keyIterator(); it.hasNext();) {
final ByteBufferIndexInput clone = it.next();
assert clone.isClone;
clone.unsetBuffers();
if (clones != null) {
for (Iterator<ByteBufferIndexInput> it = this.clones.keyIterator(); it.hasNext();) {
final ByteBufferIndexInput clone = it.next();
assert clone.isClone;
clone.unsetBuffers();
}
this.clones.clear();
}
this.clones.clear();
for (final ByteBuffer b : bufs) {
freeBuffer(b);

View File

@ -177,36 +177,6 @@ public class MMapDirectory extends FSDirectory {
return useUnmapHack;
}
/**
* Try to unmap the buffer, this method silently fails if no support
* for that in the JVM. On Windows, this leads to the fact,
* that mmapped files cannot be modified or deleted.
*/
final void cleanMapping(final ByteBuffer buffer) throws IOException {
if (useUnmapHack) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
final Method getCleanerMethod = buffer.getClass()
.getMethod("cleaner");
getCleanerMethod.setAccessible(true);
final Object cleaner = getCleanerMethod.invoke(buffer);
if (cleaner != null) {
cleaner.getClass().getMethod("clean")
.invoke(cleaner);
}
return null;
}
});
} catch (PrivilegedActionException e) {
final IOException ioe = new IOException("unable to unmap the mapped buffer");
ioe.initCause(e.getCause());
throw ioe;
}
}
}
/**
* Returns the current mmap chunk size.
* @see #MMapDirectory(File, LockFactory, int)
@ -246,14 +216,42 @@ public class MMapDirectory extends FSDirectory {
}
private final class MMapIndexInput extends ByteBufferIndexInput {
private final boolean useUnmapHack;
MMapIndexInput(String resourceDescription, RandomAccessFile raf) throws IOException {
super(resourceDescription, map(raf, 0, raf.length()), raf.length(), chunkSizePower);
super(resourceDescription, map(raf, 0, raf.length()), raf.length(), chunkSizePower, getUseUnmap());
this.useUnmapHack = getUseUnmap();
}
/**
* Try to unmap the buffer, this method silently fails if no support
* for that in the JVM. On Windows, this leads to the fact,
* that mmapped files cannot be modified or deleted.
*/
@Override
protected void freeBuffer(ByteBuffer buffer) throws IOException {
cleanMapping(buffer);
protected void freeBuffer(final ByteBuffer buffer) throws IOException {
if (useUnmapHack) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
final Method getCleanerMethod = buffer.getClass()
.getMethod("cleaner");
getCleanerMethod.setAccessible(true);
final Object cleaner = getCleanerMethod.invoke(buffer);
if (cleaner != null) {
cleaner.getClass().getMethod("clean")
.invoke(cleaner);
}
return null;
}
});
} catch (PrivilegedActionException e) {
final IOException ioe = new IOException("unable to unmap the mapped buffer");
ioe.initCause(e.getCause());
throw ioe;
}
}
}
}