Small performance improvements in ResourceLeakDetector

Motivation:

42fba015ce changed the implemention of ResourceLeakDetector to improve performance. While this was done a branch was missed that can be removed. Beside this  using a Boolean as value for the ConcurrentMap is sub-optimal as when calling remove(key, value) an uncessary instanceof check and cast is needed on each removal.

Modifications:

- Remove branch which is not needed anymore
- Replace usage of Boolean as value type of the ConcurrentMap and use our own special type which only compute hash-code one time and use a == operation for equals(...) to reduce overhead present when using Boolean.

Result:

Faster and cleaner ResourceLeakDetector.
This commit is contained in:
Norman Maurer 2016-12-01 08:13:33 +01:00 committed by Norman Maurer
parent 2de644224c
commit fd0ae840b6

View File

@ -144,7 +144,7 @@ public class ResourceLeakDetector<T> {
}
/** the collection of active resources */
private final ConcurrentMap<DefaultResourceLeak, Boolean> allLeaks = PlatformDependent.newConcurrentHashMap();
private final ConcurrentMap<DefaultResourceLeak, LeakEntry> allLeaks = PlatformDependent.newConcurrentHashMap();
private final ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
private final ConcurrentMap<String, Boolean> reportedLeaks = PlatformDependent.newConcurrentHashMap();
@ -306,20 +306,18 @@ public class ResourceLeakDetector<T> {
private int removedRecords;
DefaultResourceLeak(Object referent) {
super(referent, referent != null? refQueue : null);
super(referent, refQueue);
if (referent != null) {
Level level = getLevel();
if (level.ordinal() >= Level.ADVANCED.ordinal()) {
creationRecord = newRecord(null, 3);
} else {
creationRecord = null;
}
assert referent != null;
allLeaks.put(this, Boolean.TRUE);
Level level = getLevel();
if (level.ordinal() >= Level.ADVANCED.ordinal()) {
creationRecord = newRecord(null, 3);
} else {
creationRecord = null;
}
allLeaks.put(this, LeakEntry.INSTANCE);
}
@Override
@ -352,7 +350,7 @@ public class ResourceLeakDetector<T> {
@Override
public boolean close() {
// Use the ConcurrentMap remove method, which avoids allocating an iterator.
return allLeaks.remove(this, Boolean.TRUE);
return allLeaks.remove(this, LeakEntry.INSTANCE);
}
@Override
@ -451,4 +449,21 @@ public class ResourceLeakDetector<T> {
return buf.toString();
}
private static final class LeakEntry {
static final LeakEntry INSTANCE = new LeakEntry();
private static final int HASH = System.identityHashCode(INSTANCE);
private LeakEntry() { }
@Override
public int hashCode() {
return HASH;
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
}
}