diff --git a/htroot/PerformanceMemory_p.html b/htroot/PerformanceMemory_p.html
index e0fac875b..bc7b2cfb6 100644
--- a/htroot/PerformanceMemory_p.html
+++ b/htroot/PerformanceMemory_p.html
@@ -184,19 +184,51 @@
DNSCache |
- #[namecache.hit]# |
+ #[namecacheHit.size]# |
+ |
+ |
+ |
+ |
+
+
+ DNSCache |
+ #[namecacheMiss.size]# |
+ |
+ |
+ |
+ |
DNSNoCache |
+ |
#[namecache.noCache]# |
+ |
+ |
+ |
HashBlacklistedCache |
#[blacklistcache.size]# |
+ |
+ |
+ |
+ |
+
+
+ Search Event Cache |
+ #[searchevent.size]# |
+ #[searchevent.hit]# |
+ #[searchevent.miss]# |
+ #[searchevent.insert]# |
+ #[searchevent.delete]# |
diff --git a/htroot/PerformanceMemory_p.java b/htroot/PerformanceMemory_p.java
index 0b874e7a7..49c01b95a 100644
--- a/htroot/PerformanceMemory_p.java
+++ b/htroot/PerformanceMemory_p.java
@@ -38,6 +38,7 @@ import net.yacy.kelondro.util.FileUtils;
import net.yacy.kelondro.util.Formatter;
import net.yacy.kelondro.util.MemoryControl;
+import de.anomic.search.SearchEventCache;
import de.anomic.search.Switchboard;
import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch;
@@ -187,12 +188,15 @@ public class PerformanceMemory_p {
prop.putNum("objectMissCacheTotalMem", totalmissmem / (1024 * 1024d));
// other caching structures
- long amount = Domains.nameCacheHitSize();
- prop.putNum("namecache.hit", amount);
- amount = Domains.nameCacheNoCachingListSize();
- prop.putNum("namecache.noCache", amount);
- amount = Switchboard.urlBlacklist.blacklistCacheSize();
- prop.putNum("blacklistcache.size", amount);
+ prop.putNum("namecacheHit.size", Domains.nameCacheHitSize());
+ prop.putNum("namecacheMiss.size", Domains.nameCacheMissSize());
+ prop.putNum("namecache.noCache", Domains.nameCacheNoCachingListSize());
+ prop.putNum("blacklistcache.size", Switchboard.urlBlacklist.blacklistCacheSize());
+ prop.putNum("searchevent.size", SearchEventCache.size());
+ prop.putNum("searchevent.hit", SearchEventCache.cacheHit);
+ prop.putNum("searchevent.miss", SearchEventCache.cacheMiss);
+ prop.putNum("searchevent.insert", SearchEventCache.cacheInsert);
+ prop.putNum("searchevent.delete", SearchEventCache.cacheDelete);
// return rewrite values for templates
return prop;
}
diff --git a/source/de/anomic/search/SearchEventCache.java b/source/de/anomic/search/SearchEventCache.java
index dbd51edda..3effceecb 100644
--- a/source/de/anomic/search/SearchEventCache.java
+++ b/source/de/anomic/search/SearchEventCache.java
@@ -26,10 +26,14 @@
package de.anomic.search;
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
+import net.yacy.cora.storage.ARC;
+import net.yacy.cora.storage.ConcurrentARC;
+import net.yacy.kelondro.util.MemoryControl;
import net.yacy.repository.LoaderDispatcher;
import de.anomic.crawler.ResultURLs;
@@ -37,33 +41,43 @@ import de.anomic.yacy.yacySeedDB;
public class SearchEventCache {
- private static ConcurrentHashMap lastEvents = new ConcurrentHashMap(); // a cache for objects from this class: re-use old search requests
- public static final long eventLifetime = 60000; // the time an event will stay in the cache, 1 Minute
-
+ private static ARC lastEvents = new ConcurrentARC(1000, Runtime.getRuntime().availableProcessors() * 4); // a cache for objects from this class: re-use old search requests
+ public static final long eventLifetime = 600000; // the time an event will stay in the cache, 10 Minutes
+ public static final long memlimit = 100 * 1024 * 1024; // 100 MB
public static String lastEventID = "";
+ public static long cacheInsert = 0, cacheHit = 0, cacheMiss = 0, cacheDelete = 0;
+
+ public static int size() {
+ return lastEvents.size();
+ }
public static void put(String eventID, SearchEvent event) {
lastEventID = eventID;
- lastEvents.put(eventID, event);
+ SearchEvent oldEvent = lastEvents.put(eventID, event);
+ if (oldEvent == null) cacheInsert++;
}
public static void cleanupEvents(final boolean all) {
// remove old events in the event cache
- final Iterator i = lastEvents.values().iterator();
- SearchEvent event;
- while (i.hasNext()) {
- event = i.next();
- if (all || event.getEventTime() + eventLifetime < System.currentTimeMillis()) {
- event.cleanup();
-
- // remove the event
- i.remove();
+ List delete = new ArrayList();
+ // the less memory is there, the less time is acceptable for elements in the cache
+ long memx = MemoryControl.available();
+ long acceptTime = memx > memlimit ? eventLifetime : memx * eventLifetime / memlimit;
+ for (Map.Entry event: lastEvents) {
+ if (all || event.getValue().getEventTime() + acceptTime < System.currentTimeMillis()) {
+ event.getValue().cleanup();
+ delete.add(event.getKey());
}
}
+ // remove the events
+ cacheDelete += delete.size();
+ for (String k: delete) lastEvents.remove(k);
}
public static SearchEvent getEvent(final String eventID) {
- return lastEvents.get(eventID);
+ SearchEvent event = lastEvents.get(eventID);
+ if (event == null) cacheMiss++; else cacheHit++;
+ return event;
}
public static SearchEvent getEvent(
@@ -76,11 +90,13 @@ public class SearchEventCache {
String id = query.id(false);
SearchEvent event = SearchEventCache.lastEvents.get(id);
+ if (event == null) cacheMiss++; else cacheHit++;
if (Switchboard.getSwitchboard() != null && !Switchboard.getSwitchboard().crawlQueues.noticeURL.isEmpty() && event != null && System.currentTimeMillis() - event.getEventTime() > 60000) {
// if a local crawl is ongoing, don't use the result from the cache to use possibly more results that come from the current crawl
// to prevent that this happens during a person switches between the different result pages, a re-search happens no more than
// once a minute
SearchEventCache.lastEvents.remove(id);
+ cacheDelete++;
event = null;
} else {
if (event != null) {