diff --git a/engine/src/main/java/org/archive/crawler/util/TopNSet.java b/engine/src/main/java/org/archive/crawler/util/TopNSet.java index d1e85792..bdfa2d0b 100644 --- a/engine/src/main/java/org/archive/crawler/util/TopNSet.java +++ b/engine/src/main/java/org/archive/crawler/util/TopNSet.java @@ -20,13 +20,15 @@ package org.archive.crawler.util; import java.io.Serializable; -import java.util.HashMap; import java.util.SortedSet; import java.util.TreeSet; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; import org.archive.util.Histotable; +import com.google.common.collect.MapMaker; + /** * Counting Set which only remembers the 'top N' of all String values * reported (with counts) to it. Precise if counts reported for a @@ -46,15 +48,15 @@ public class TopNSet implements Serializable { private static final long serialVersionUID = 1L; int maxsize; - HashMap set; - long smallestKnownValue; - String smallestKnownKey; - long largestKnownValue; - String largestKnownKey; + ConcurrentMap set; + volatile long smallestKnownValue; + volatile String smallestKnownKey; + volatile long largestKnownValue; + volatile String largestKnownKey; public TopNSet(int size){ maxsize = size; - set = new HashMap(size); + set = new MapMaker().concurrencyLevel(64).makeMap(); } /** @@ -65,9 +67,20 @@ public class TopNSet implements Serializable { * @param key String key to update * @param value long new total value (*not* increment/decrement) */ - public synchronized void update(String key, long value){ - if(set.containsKey(key) || set.size() < maxsize || value > smallestKnownValue) { - set.put(key,value); + public void update(String key, long value){ + // handle easy cases without synchronization + if(set.size() maxsize) { set.remove(smallestKnownKey); updateBounds(); @@ -92,7 +105,7 @@ public class TopNSet implements Serializable { * After an operation invalidating the previous largest/smallest entry, * find the new largest/smallest. */ - protected void updateBounds(){ + public synchronized void updateBounds(){ // freshly determine smallestKnownValue = Long.MAX_VALUE; largestKnownValue = Long.MIN_VALUE; @@ -113,7 +126,7 @@ public class TopNSet implements Serializable { * Make internal map available (for checkpoint/restore purposes). * @return HashMap */ - public HashMap getTopSet() { + public ConcurrentMap getTopSet() { return set; }