Skip to content

Commit

Permalink
ISPN-8517 Lazily ressurect ice fromMemory
Browse files Browse the repository at this point in the history
* Reuse address pointer for compute remove
* Don't resurrect value if not needed
  • Loading branch information
wburns committed Nov 9, 2017
1 parent 42baa44 commit ff04a77
Showing 1 changed file with 50 additions and 27 deletions.
Expand Up @@ -138,32 +138,43 @@ private InternalCacheEntry<WrappedBytes, WrappedBytes> peekOrGet(Object k, boole
lock.lock();
try {
checkDeallocation();
long address = memoryLookup.getMemoryAddress(k);
if (address == 0) {
long bucketAddress = memoryLookup.getMemoryAddress(k);
if (bucketAddress == 0) {
return null;
}

return performGet(address, k, peek);
long actualAddress = performGet(bucketAddress, k);
if (actualAddress != 0) {
InternalCacheEntry<WrappedBytes, WrappedBytes> ice = offHeapEntryFactory.fromMemory(actualAddress);
if (!peek) {
entryRetrieved(actualAddress);
}
return ice;
}
} finally {
lock.unlock();
}
return null;
}

protected InternalCacheEntry<WrappedBytes, WrappedBytes> performGet(long address, Object k, boolean peek) {
/**
* Gets the actual address for the given key in the given bucket or 0 if it isn't present
* @param bucketHeadAddress the starting address of the address hash
* @param k the key to retrieve the address for it if matches
* @return the address matching the key or 0
*/
protected long performGet(long bucketHeadAddress, Object k) {
WrappedBytes wrappedKey = toWrapper(k);
long address = bucketHeadAddress;
while (address != 0) {
long nextAddress = offHeapEntryFactory.getNext(address);
InternalCacheEntry<WrappedBytes, WrappedBytes> ice = offHeapEntryFactory.fromMemory(address);
if (wrappedKey.equalsWrappedBytes(ice.getKey())) {
if (!peek) {
entryRetrieved(address);
}
return ice;
if (offHeapEntryFactory.equalsKey(address, wrappedKey)) {
return address;
} else {
address = nextAddress;
}
}
return null;
return 0;
}

@Override
Expand All @@ -174,7 +185,7 @@ public void put(WrappedBytes key, WrappedBytes value, Metadata metadata) {
checkDeallocation();
long newAddress = offHeapEntryFactory.create(key, value, metadata);
long address = memoryLookup.getMemoryAddress(key);
performPut(address, newAddress, key);
performPut(address, 0, newAddress, key);
} finally {
lock.unlock();
}
Expand All @@ -183,27 +194,31 @@ public void put(WrappedBytes key, WrappedBytes value, Metadata metadata) {
/**
* Performs the actual put operation putting the new address into the memory lookups. The write lock for the given
* key <b>must</b> be held before calling this method.
* @param address the entry address of the first element in the lookup
* @param bucketHeadAddress the entry address of the first element in the lookup
* @param actualAddress the actual address if it is known or 0. By passing this != 0 equality checks can be bypassed.
* If a value of 0 is provided this will use key equality.
* @param newAddress the address of the new entry
* @param key the key of the entry
*/
protected void performPut(long address, long newAddress, WrappedBytes key) {
protected void performPut(long bucketHeadAddress, long actualAddress, long newAddress, WrappedBytes key) {
// Have to start new linked node list
if (address == 0) {
if (bucketHeadAddress == 0) {
memoryLookup.putMemoryAddress(key, newAddress);
entryCreated(newAddress);
size.incrementAndGet();
} else {
boolean replaceHead = false;
// Whether the key was found or not - short circuit equality checks
boolean foundKey = false;
long address = bucketHeadAddress;
// Holds the previous linked list address
long prevAddress = 0;
// Keep looping until we get the tail end - we always append the put to the end
while (address != 0) {
long nextAddress = offHeapEntryFactory.getNext(address);
if (!foundKey) {
if (offHeapEntryFactory.equalsKey(address, key)) {
// If the actualAddress was not known check key equality otherwise just compare with the address
if (actualAddress == 0 ? offHeapEntryFactory.equalsKey(address, key) : actualAddress == address) {
entryReplaced(newAddress, address);
foundKey = true;
// If this is true it means this was the first node in the linked list
Expand Down Expand Up @@ -343,7 +358,7 @@ protected InternalCacheEntry<WrappedBytes, WrappedBytes> performRemove(long buck
while (address != 0) {
long nextAddress = offHeapEntryFactory.getNext(address);
boolean removeThisAddress;
// If the actualAddress was not known, check key equality otherwise just compare with the address
// If the actualAddress was not known check key equality otherwise just compare with the address
removeThisAddress = actualAddress == 0 ? offHeapEntryFactory.equalsKey(address, wba) : actualAddress == address;
if (removeThisAddress) {
if (requireReturn) {
Expand Down Expand Up @@ -503,13 +518,13 @@ public void evict(WrappedBytes key) {
lock.lock();
try {
checkDeallocation();
long address = memoryLookup.getMemoryAddress(key);
if (address != 0) {
// TODO: this could be more efficient
InternalCacheEntry<WrappedBytes, WrappedBytes> ice = performGet(address, key, true);
if (ice != null) {
long bucketAddress = memoryLookup.getMemoryAddress(key);
if (bucketAddress != 0) {
long actualAddress = performGet(bucketAddress, key);
if (actualAddress != 0) {
InternalCacheEntry<WrappedBytes, WrappedBytes> ice = offHeapEntryFactory.fromMemory(actualAddress);
passivator.passivate(ice);
performRemove(address, 0, key, false);
performRemove(bucketAddress, actualAddress, key, false);
}
}
} finally {
Expand All @@ -524,16 +539,24 @@ public InternalCacheEntry<WrappedBytes, WrappedBytes> compute(WrappedBytes key,
lock.lock();
try {
checkDeallocation();
long address = memoryLookup.getMemoryAddress(key);
InternalCacheEntry<WrappedBytes, WrappedBytes> prev = address == 0 ? null : performGet(address, key, true);
long bucketAddress = memoryLookup.getMemoryAddress(key);
long actualAddress = bucketAddress == 0 ? 0 : performGet(bucketAddress, key);
InternalCacheEntry<WrappedBytes, WrappedBytes> prev;
if (actualAddress != 0) {
prev = offHeapEntryFactory.fromMemory(actualAddress);
} else {
prev = null;
}
InternalCacheEntry<WrappedBytes, WrappedBytes> result = action.compute(key, prev, internalEntryFactory);
if (prev == result) {
// noop
} else if (result != null) {
long newAddress = offHeapEntryFactory.create(key, result.getValue(), result.getMetadata());
performPut(address, newAddress, key);
// TODO: Technically actualAddress could be a 0 and bucketAddress != 0, which means we will loop through
// entire bucket for no reason as it will never match (doing key equality checks)
performPut(bucketAddress, actualAddress, newAddress, key);
} else {
performRemove(address, 0, key, false);
performRemove(bucketAddress, actualAddress, key, false);
}
return result;
} finally {
Expand Down

0 comments on commit ff04a77

Please sign in to comment.