package edu.stanford.nlp.sempre.tables.lambdadcs;
import java.util.*;
import fig.basic.*;
/**
* Cache the executed values of an executor.
*
* The cache should be cleared once the parser finishes each example.
* The metakey Object specifies the current example.
* When the metakey is changed, the cache is cleared.
*
* @author ppasupat
*/
public final class ExecutorCache {
public static class Options {
@Option(gloss = "maximum number of values to retain")
public int maxCacheSize = 1000000;
@Option(gloss = "minimum number of values evicted before garbage collection")
public int cacheGCThreshold = 10000000;
@Option public int verbose = 0;
}
public static Options opts = new Options();
// Default cache
public static final ExecutorCache singleton = new ExecutorCache();
private Object currentMetakey = null;
private final Map<Object, Object> cache;
private int accumSize = 0;
public ExecutorCache() {
cache = new HashMap<>();
}
public synchronized Object get(Object metakey, Object key) {
if (currentMetakey != metakey) {
clearCache(metakey);
}
Object value = cache.get(key);
if (opts.verbose >= 1)
LogInfo.logs("[GET =>] %s => %s", key, value);
return value;
}
public synchronized void put(Object metakey, Object key, Object value) {
if (currentMetakey != metakey) {
clearCache(metakey);
}
if (opts.verbose >= 1)
LogInfo.logs("[<= PUT] %s <= %s", key, value);
if (cache.size() < opts.maxCacheSize)
cache.put(key, value);
}
public void clearCache(Object metakey) {
accumSize += cache.size();
cache.clear();
// Garbage collect
if (accumSize >= opts.cacheGCThreshold) {
System.gc();
accumSize = 0;
}
if (opts.verbose >= 1)
LogInfo.logs("[clearCache] metakey = %s", metakey);
currentMetakey = metakey;
}
}