mirror of
https://github.com/webbukkit/dynmap.git
synced 2025-01-04 06:57:43 +01:00
Add weak reference based cache for chunk snapshots
This commit is contained in:
parent
eb87231926
commit
66ca5199e3
@ -197,6 +197,12 @@ public class DynmapPlugin extends JavaPlugin {
|
|||||||
return enabledTriggers.contains(s);
|
return enabledTriggers.contains(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean onplace;
|
||||||
|
private boolean onbreak;
|
||||||
|
private boolean onsnow;
|
||||||
|
private boolean onleaves;
|
||||||
|
private boolean onburn;
|
||||||
|
|
||||||
public void registerEvents() {
|
public void registerEvents() {
|
||||||
final PluginManager pm = getServer().getPluginManager();
|
final PluginManager pm = getServer().getPluginManager();
|
||||||
final MapManager mm = mapManager;
|
final MapManager mm = mapManager;
|
||||||
@ -204,50 +210,61 @@ public class DynmapPlugin extends JavaPlugin {
|
|||||||
// To trigger rendering.
|
// To trigger rendering.
|
||||||
{
|
{
|
||||||
BlockListener renderTrigger = new BlockListener() {
|
BlockListener renderTrigger = new BlockListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockPlace(BlockPlaceEvent event) {
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
if(event.isCancelled())
|
if(event.isCancelled())
|
||||||
return;
|
return;
|
||||||
mm.touch(event.getBlockPlaced().getLocation());
|
if(onplace)
|
||||||
|
mm.touch(event.getBlockPlaced().getLocation());
|
||||||
|
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
if(event.isCancelled())
|
if(event.isCancelled())
|
||||||
return;
|
return;
|
||||||
mm.touch(event.getBlock().getLocation());
|
if(onbreak)
|
||||||
|
mm.touch(event.getBlock().getLocation());
|
||||||
|
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onSnowForm(SnowFormEvent event) {
|
public void onSnowForm(SnowFormEvent event) {
|
||||||
if(event.isCancelled())
|
if(event.isCancelled())
|
||||||
return;
|
return;
|
||||||
mm.touch(event.getBlock().getLocation());
|
if(onsnow)
|
||||||
|
mm.touch(event.getBlock().getLocation());
|
||||||
|
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLeavesDecay(LeavesDecayEvent event) {
|
public void onLeavesDecay(LeavesDecayEvent event) {
|
||||||
if(event.isCancelled())
|
if(event.isCancelled())
|
||||||
return;
|
return;
|
||||||
mm.touch(event.getBlock().getLocation());
|
if(onleaves)
|
||||||
|
mm.touch(event.getBlock().getLocation());
|
||||||
|
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockBurn(BlockBurnEvent event) {
|
public void onBlockBurn(BlockBurnEvent event) {
|
||||||
if(event.isCancelled())
|
if(event.isCancelled())
|
||||||
return;
|
return;
|
||||||
mm.touch(event.getBlock().getLocation());
|
if(onburn)
|
||||||
|
mm.touch(event.getBlock().getLocation());
|
||||||
|
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (isTrigger("blockplaced"))
|
onplace = isTrigger("blockplaced");
|
||||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_PLACE, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_PLACE, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||||
if (isTrigger("blockbreak"))
|
onbreak = isTrigger("blockbreak");
|
||||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BREAK, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BREAK, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||||
if (isTrigger("snowform"))
|
onsnow = isTrigger("snowform");
|
||||||
pm.registerEvent(org.bukkit.event.Event.Type.SNOW_FORM, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
pm.registerEvent(org.bukkit.event.Event.Type.SNOW_FORM, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||||
if (isTrigger("leavesdecay"))
|
onleaves = isTrigger("leavesdecay");
|
||||||
pm.registerEvent(org.bukkit.event.Event.Type.LEAVES_DECAY, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
pm.registerEvent(org.bukkit.event.Event.Type.LEAVES_DECAY, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||||
if (isTrigger("blockburn"))
|
onburn = isTrigger("blockburn");
|
||||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BURN, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BURN, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PlayerListener renderTrigger = new PlayerListener() {
|
PlayerListener renderTrigger = new PlayerListener() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.dynmap;
|
package org.dynmap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -15,6 +16,8 @@ import java.util.concurrent.ScheduledFuture;
|
|||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.bukkit.ChunkSnapshot;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
@ -22,9 +25,11 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.dynmap.DynmapWorld.AutoGenerateOption;
|
import org.dynmap.DynmapWorld.AutoGenerateOption;
|
||||||
import org.dynmap.debug.Debug;
|
import org.dynmap.debug.Debug;
|
||||||
import org.dynmap.hdmap.HDMapManager;
|
import org.dynmap.hdmap.HDMapManager;
|
||||||
|
import org.dynmap.utils.LRULinkedHashMap;
|
||||||
import org.dynmap.utils.LegacyMapChunkCache;
|
import org.dynmap.utils.LegacyMapChunkCache;
|
||||||
import org.dynmap.utils.MapChunkCache;
|
import org.dynmap.utils.MapChunkCache;
|
||||||
import org.dynmap.utils.NewMapChunkCache;
|
import org.dynmap.utils.NewMapChunkCache;
|
||||||
|
import org.dynmap.utils.SnapshotCache;
|
||||||
|
|
||||||
public class MapManager {
|
public class MapManager {
|
||||||
public AsynchronousQueue<MapTile> tileQueue;
|
public AsynchronousQueue<MapTile> tileQueue;
|
||||||
@ -50,6 +55,7 @@ public class MapManager {
|
|||||||
|
|
||||||
public static MapManager mapman; /* Our singleton */
|
public static MapManager mapman; /* Our singleton */
|
||||||
public HDMapManager hdmapman;
|
public HDMapManager hdmapman;
|
||||||
|
public SnapshotCache sscache;
|
||||||
|
|
||||||
/* Thread pool for processing renders */
|
/* Thread pool for processing renders */
|
||||||
private DynmapScheduledThreadPoolExecutor renderpool;
|
private DynmapScheduledThreadPoolExecutor renderpool;
|
||||||
@ -328,7 +334,8 @@ public class MapManager {
|
|||||||
hdmapman.loadHDShaders(shadercfg);
|
hdmapman.loadHDShaders(shadercfg);
|
||||||
hdmapman.loadHDPerspectives(perspectivecfg);
|
hdmapman.loadHDPerspectives(perspectivecfg);
|
||||||
hdmapman.loadHDLightings(lightingscfg);
|
hdmapman.loadHDLightings(lightingscfg);
|
||||||
|
sscache = new SnapshotCache(configuration.getInteger("snapshotcachesize", 500));
|
||||||
|
|
||||||
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
|
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MapTile t) {
|
public void handle(MapTile t) {
|
||||||
@ -623,6 +630,7 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
sender.sendMessage(" TOTALS: processed=" + tot.loggedcnt + ", rendered=" + tot.renderedcnt +
|
sender.sendMessage(" TOTALS: processed=" + tot.loggedcnt + ", rendered=" + tot.renderedcnt +
|
||||||
", updated=" + tot.updatedcnt + ", transparent=" + tot.transparentcnt);
|
", updated=" + tot.updatedcnt + ", transparent=" + tot.transparentcnt);
|
||||||
|
sender.sendMessage(" Cache hit rate: " + sscache.getHitRate() + "%");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Reset statistics
|
* Reset statistics
|
||||||
@ -639,6 +647,7 @@ public class MapManager {
|
|||||||
ms.transparentcnt = 0;
|
ms.transparentcnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sscache.resetStats();
|
||||||
sender.sendMessage("Tile Render Statistics reset");
|
sender.sendMessage("Tile Render Statistics reset");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.dynmap.Client;
|
import org.dynmap.Client;
|
||||||
import org.dynmap.Color;
|
import org.dynmap.Color;
|
||||||
@ -248,7 +249,14 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
short[] model = scalemodels.getScaledModel(blocktypeid, blockdata);
|
short[] model = scalemodels.getScaledModel(blocktypeid, blockdata);
|
||||||
if(model != null) {
|
if(model != null) {
|
||||||
missed = raytraceSubblock(model);
|
missed = raytraceSubblock(model);
|
||||||
skip_light_update = true; /* Some blocks are light blocking, but not fully blocking - this sucks */
|
/* Some blocks are light blocking, but not fully blocking - this sucks */
|
||||||
|
switch(blocktypeid) {
|
||||||
|
case 53: /* Wood stairs */
|
||||||
|
case 44: /* Slabs */
|
||||||
|
case 67: /* Cobblestone stairs */
|
||||||
|
skip_light_update = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subalpha = -1;
|
subalpha = -1;
|
||||||
@ -524,6 +532,10 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
int x = t.tx;
|
int x = t.tx;
|
||||||
int y = t.ty;
|
int y = t.ty;
|
||||||
return new MapTile[] {
|
return new MapTile[] {
|
||||||
|
new HDMapTile(w, this, x - 1, y - 1),
|
||||||
|
new HDMapTile(w, this, x + 1, y - 1),
|
||||||
|
new HDMapTile(w, this, x - 1, y + 1),
|
||||||
|
new HDMapTile(w, this, x + 1, y + 1),
|
||||||
new HDMapTile(w, this, x, y - 1),
|
new HDMapTile(w, this, x, y - 1),
|
||||||
new HDMapTile(w, this, x + 1, y),
|
new HDMapTile(w, this, x + 1, y),
|
||||||
new HDMapTile(w, this, x, y + 1),
|
new HDMapTile(w, this, x, y + 1),
|
||||||
|
@ -128,6 +128,10 @@ public class KzedMap extends MapType {
|
|||||||
DynmapWorld world = tile.getDynmapWorld();
|
DynmapWorld world = tile.getDynmapWorld();
|
||||||
MapTileRenderer renderer = t.renderer;
|
MapTileRenderer renderer = t.renderer;
|
||||||
return new MapTile[] {
|
return new MapTile[] {
|
||||||
|
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py + tileHeight),
|
||||||
|
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py - tileHeight),
|
||||||
|
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py - tileHeight),
|
||||||
|
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py + tileHeight),
|
||||||
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py),
|
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py),
|
||||||
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py),
|
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py),
|
||||||
new KzedMapTile(world, this, renderer, t.px, t.py - tileHeight),
|
new KzedMapTile(world, this, renderer, t.px, t.py - tileHeight),
|
||||||
|
@ -319,6 +319,20 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Check if cached chunk snapshot found */
|
||||||
|
ChunkSnapshot ss = MapManager.mapman.sscache.getSnapshot(w.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||||
|
if(ss != null) {
|
||||||
|
if(!vis) {
|
||||||
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
|
ss = STONE;
|
||||||
|
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
|
||||||
|
ss = OCEAN;
|
||||||
|
else
|
||||||
|
ss = EMPTY;
|
||||||
|
}
|
||||||
|
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
||||||
boolean didload = w.loadChunk(chunk.x, chunk.z, false);
|
boolean didload = w.loadChunk(chunk.x, chunk.z, false);
|
||||||
boolean didgenerate = false;
|
boolean didgenerate = false;
|
||||||
@ -327,7 +341,6 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
didgenerate = didload = w.loadChunk(chunk.x, chunk.z, true);
|
didgenerate = didload = w.loadChunk(chunk.x, chunk.z, true);
|
||||||
/* If it did load, make cache of it */
|
/* If it did load, make cache of it */
|
||||||
if(didload) {
|
if(didload) {
|
||||||
ChunkSnapshot ss = null;
|
|
||||||
if(!vis) {
|
if(!vis) {
|
||||||
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
ss = STONE;
|
ss = STONE;
|
||||||
@ -351,6 +364,8 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
ss = c.getChunkSnapshot();
|
ss = c.getChunkSnapshot();
|
||||||
|
if(ss != null)
|
||||||
|
MapManager.mapman.sscache.putSnapshot(w.getName(), chunk.x, chunk.z, ss, blockdata, biome, biomeraw, highesty);
|
||||||
}
|
}
|
||||||
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
||||||
}
|
}
|
||||||
|
145
src/main/java/org/dynmap/utils/SnapshotCache.java
Normal file
145
src/main/java/org/dynmap/utils/SnapshotCache.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package org.dynmap.utils;
|
||||||
|
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.ChunkSnapshot;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
|
||||||
|
public class SnapshotCache {
|
||||||
|
private CacheHashMap snapcache;
|
||||||
|
private ReferenceQueue<ChunkSnapshot> refqueue;
|
||||||
|
private long cache_attempts;
|
||||||
|
private long cache_success;
|
||||||
|
|
||||||
|
private static class CacheRec {
|
||||||
|
WeakReference<ChunkSnapshot> ref;
|
||||||
|
boolean hasbiome;
|
||||||
|
boolean hasrawbiome;
|
||||||
|
boolean hasblockdata;
|
||||||
|
boolean hashighesty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
|
||||||
|
private int limit;
|
||||||
|
private IdentityHashMap<WeakReference<ChunkSnapshot>, String> reverselookup;
|
||||||
|
|
||||||
|
public CacheHashMap(int lim) {
|
||||||
|
super(16, (float)0.75, true);
|
||||||
|
limit = lim;
|
||||||
|
reverselookup = new IdentityHashMap<WeakReference<ChunkSnapshot>, String>();
|
||||||
|
}
|
||||||
|
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
|
||||||
|
boolean remove = (size() >= limit);
|
||||||
|
if(remove) {
|
||||||
|
reverselookup.remove(last.getValue().ref);
|
||||||
|
}
|
||||||
|
return remove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create snapshot cache
|
||||||
|
*/
|
||||||
|
public SnapshotCache(int max_size) {
|
||||||
|
snapcache = new CacheHashMap(max_size);
|
||||||
|
refqueue = new ReferenceQueue<ChunkSnapshot>();
|
||||||
|
}
|
||||||
|
private String getKey(Location loc) {
|
||||||
|
return loc.getWorld().getName() + ":" + (loc.getBlockX()>>4) + ":" + (loc.getBlockZ()>>4);
|
||||||
|
}
|
||||||
|
private String getKey(String w, int cx, int cz) {
|
||||||
|
return w + ":" + cx + ":" + cz;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Invalidate cached snapshot, if in cache
|
||||||
|
*/
|
||||||
|
public void invalidateSnapshot(Location loc) {
|
||||||
|
String key = getKey(loc);
|
||||||
|
CacheRec rec = snapcache.remove(key);
|
||||||
|
if(rec != null) {
|
||||||
|
snapcache.reverselookup.remove(rec.ref);
|
||||||
|
rec.ref.clear();
|
||||||
|
}
|
||||||
|
processRefQueue();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Look for chunk snapshot in cache
|
||||||
|
*/
|
||||||
|
public ChunkSnapshot getSnapshot(String w, int chunkx, int chunkz,
|
||||||
|
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
||||||
|
String key = getKey(w, chunkx, chunkz);
|
||||||
|
processRefQueue();
|
||||||
|
ChunkSnapshot ss = null;
|
||||||
|
CacheRec rec = snapcache.get(key);
|
||||||
|
if(rec != null) {
|
||||||
|
ss = rec.ref.get();
|
||||||
|
if(ss == null) {
|
||||||
|
snapcache.reverselookup.remove(rec.ref);
|
||||||
|
snapcache.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ss != null) {
|
||||||
|
if((blockdata && (!rec.hasblockdata)) ||
|
||||||
|
(biome && (!rec.hasbiome)) ||
|
||||||
|
(biomeraw && (!rec.hasrawbiome)) ||
|
||||||
|
(highesty && (!rec.hashighesty))) {
|
||||||
|
ss = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_attempts++;
|
||||||
|
if(ss != null) cache_success++;
|
||||||
|
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add chunk snapshot to cache
|
||||||
|
*/
|
||||||
|
public void putSnapshot(String w, int chunkx, int chunkz, ChunkSnapshot ss,
|
||||||
|
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
||||||
|
String key = getKey(w, chunkx, chunkz);
|
||||||
|
processRefQueue();
|
||||||
|
CacheRec rec = new CacheRec();
|
||||||
|
rec.hasblockdata = blockdata;
|
||||||
|
rec.hasbiome = biome;
|
||||||
|
rec.hasrawbiome = biomeraw;
|
||||||
|
rec.hashighesty = highesty;
|
||||||
|
rec.ref = new WeakReference<ChunkSnapshot>(ss, refqueue);
|
||||||
|
CacheRec prevrec = snapcache.put(key, rec);
|
||||||
|
if(prevrec != null) {
|
||||||
|
snapcache.reverselookup.remove(prevrec.ref);
|
||||||
|
}
|
||||||
|
snapcache.reverselookup.put(rec.ref, key);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Process reference queue
|
||||||
|
*/
|
||||||
|
private void processRefQueue() {
|
||||||
|
Reference<? extends ChunkSnapshot> ref;
|
||||||
|
while((ref = refqueue.poll()) != null) {
|
||||||
|
String k = snapcache.reverselookup.get(ref);
|
||||||
|
if(k != null) snapcache.remove(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get hit rate (percent)
|
||||||
|
*/
|
||||||
|
public double getHitRate() {
|
||||||
|
if(cache_attempts > 0) {
|
||||||
|
return (100.0*cache_success)/(double)cache_attempts;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reset cache stats
|
||||||
|
*/
|
||||||
|
public void resetStats() {
|
||||||
|
cache_attempts = cache_success = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user