Skip to content

Commit

Permalink
Switch from ArrayList to Object[] for slight speed up (no dynamic hea…
Browse files Browse the repository at this point in the history
…p growth needed).
  • Loading branch information
jdereg committed Jun 23, 2024
1 parent 8ea699f commit 46dc3aa
Showing 1 changed file with 19 additions and 20 deletions.
39 changes: 19 additions & 20 deletions src/main/java/com/cedarsoftware/util/LRUCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -67,18 +67,20 @@ void updateTimestamp() {
}

/**
* Create a LRUCache with the maximum capacity of 'capacity.' Note, the LRUCache could temporarily exceed the
* capacity, however, it will quickly reduce to that amount. This time is configurable and defaults to 10ms.
* Create a LRUCache with the maximum capacity of 'capacity.' Note, the LRUCache could temporarily exceed the
* capacity, however, it will quickly reduce to that amount. This time is configurable and defaults to 10ms.
*
* @param capacity int maximum size for the LRU cache.
*/
public LRUCache(int capacity) {
this(capacity, 10);
}

/**
* Create a LRUCache with the maximum capacity of 'capacity.' Note, the LRUCache could temporarily exceed the
* capacity, however, it will quickly reduce to that amount. This time is configurable via the cleanupDelay
* Create a LRUCache with the maximum capacity of 'capacity.' Note, the LRUCache could temporarily exceed the
* capacity, however, it will quickly reduce to that amount. This time is configurable via the cleanupDelay
* parameter.
*
* @param capacity int maximum size for the LRU cache.
* @param cleanupDelayMillis int milliseconds before scheduling a cleanup (reduction to capacity if the cache currently
* exceeds it).
Expand All @@ -89,14 +91,15 @@ public LRUCache(int capacity, int cleanupDelayMillis) {
this.cleanupDelayMillis = cleanupDelayMillis;
}

@SuppressWarnings("unchecked")
private void cleanup() {
int size = cache.size();
if (size > capacity) {
List<Node<K>> nodes = new ArrayList<>(cache.values());
nodes.sort(Comparator.comparingLong(node -> node.timestamp));
Node<K>[] nodes = cache.values().toArray(new Node[0]);
Arrays.sort(nodes, Comparator.comparingLong(node -> node.timestamp));
int nodesToRemove = size - capacity;
for (int i = 0; i < nodesToRemove; i++) {
Node<K> node = nodes.get(i);
Node<K> node = nodes[i];
cache.remove(toCacheItem(node.key), node);
}
}
Expand Down Expand Up @@ -127,7 +130,7 @@ public V put(K key, V value) {
if (oldNode != null) {
newNode.updateTimestamp();
return fromCacheItem(oldNode.value);
} else if (size() > capacity) {
} else if (cache.size() > capacity) {
scheduleCleanup();
}
return null;
Expand Down Expand Up @@ -198,8 +201,10 @@ public Collection<V> values() {

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Map)) return false;
if (this == o)
return true;
if (!(o instanceof Map))
return false;
Map<?, ?> other = (Map<?, ?>) o;
return entrySet().equals(other.entrySet());
}
Expand All @@ -222,7 +227,7 @@ public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
for (Node<K> node : cache.values()) {
sb.append((K)fromCacheItem(node.key)).append("=").append((V)fromCacheItem(node.value)).append(", ");
sb.append((K) fromCacheItem(node.key)).append("=").append((V) fromCacheItem(node.value)).append(", ");
}
if (sb.length() > 1) {
sb.setLength(sb.length() - 2); // Remove trailing comma and space
Expand All @@ -233,14 +238,8 @@ public String toString() {

// Schedule a delayed cleanup
private void scheduleCleanup() {
if (cache.size() > capacity && cleanupScheduled.compareAndSet(false, true)) {
executorService.schedule(() -> {
cleanup();
// Check if another cleanup is needed after the current one
if (cache.size() > capacity) {
scheduleCleanup();
}
}, cleanupDelayMillis, TimeUnit.MILLISECONDS);
if (cleanupScheduled.compareAndSet(false, true)) {
executorService.schedule(this::cleanup, cleanupDelayMillis, TimeUnit.MILLISECONDS);
}
}

Expand Down

0 comments on commit 46dc3aa

Please sign in to comment.