diff --git a/src/main/java/bdv/cache/iotiming/IoTimeBudget.java b/src/main/java/bdv/cache/iotiming/IoTimeBudget.java
index 63bf4cf9c0cdf3aa246effbd306cd3beaf5f0f2f..9374570f677304a4116ecdbcecdb6c68dc3b9828 100644
--- a/src/main/java/bdv/cache/iotiming/IoTimeBudget.java
+++ b/src/main/java/bdv/cache/iotiming/IoTimeBudget.java
@@ -87,4 +87,18 @@ public class IoTimeBudget
 		for ( ; l < budget.length && budget[ l ] > budget[ l - 1 ]; ++l )
 			budget[ l ] = budget[ l - 1 ];
 	}
+
+	/**
+	 * Returns how much time is left for the specified priority level.
+	 *
+	 * @param level
+	 *            priority level. must be greater &ge; 0.
+	 * @return time left for the specified priority level.
+	 */
+	public long estimateTimeLeft( final int level )
+	{
+		final long[] b = budget;
+		final int blevel = Math.min( level, b.length - 1 );
+		return b[ blevel ];
+	}
 }
diff --git a/src/main/java/bdv/cache/revised/SoftRefCache.java b/src/main/java/bdv/cache/revised/SoftRefCache.java
index 4bd3eecf10a219e0d6d444d77fa322c5fc4af769..a9a392db9e98e9c68e6d47872a1335d6ba5305e4 100644
--- a/src/main/java/bdv/cache/revised/SoftRefCache.java
+++ b/src/main/java/bdv/cache/revised/SoftRefCache.java
@@ -25,17 +25,17 @@ public class SoftRefCache< K, V > implements Cache< K, V >
 
 		public void clean()
 		{
-			map.remove( entry.getKey(), entry );
+			map.remove( entry.key, entry );
 		}
 	}
 
 	final class Entry
 	{
-		private final K key;
+		final K key;
 
 		private SoftReference< V > ref;
 
-		private boolean loaded;
+		boolean loaded;
 
 		public Entry( final K key )
 		{
@@ -44,11 +44,6 @@ public class SoftRefCache< K, V > implements Cache< K, V >
 			this.loaded = false;
 		}
 
-		public K getKey()
-		{
-			return key;
-		}
-
 		public V getValue()
 		{
 			return ref.get();
@@ -59,11 +54,6 @@ public class SoftRefCache< K, V > implements Cache< K, V >
 			this.loaded = true;
 			this.ref = new CacheSoftReference( value, this );
 		}
-
-		public boolean wasLoaded()
-		{
-			return loaded;
-		}
 	}
 
 	@Override
@@ -82,7 +72,7 @@ public class SoftRefCache< K, V > implements Cache< K, V >
 		{
 			synchronized ( entry )
 			{
-				if ( entry.wasLoaded() )
+				if ( entry.loaded )
 				{
 					value = entry.getValue();
 					if ( value == null )
diff --git a/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java b/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java
index 1ebae175ccab5ed5e62459c22794047fb8bd594a..383ed99191a3eb710163f696680ea22edc506c2f 100644
--- a/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java
+++ b/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java
@@ -48,6 +48,9 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 		}
 	}
 
+	/*
+	 * Possible states of Entry.loaded
+	 */
 	static final int NOTLOADED = 0;
 	static final int INVALID = 1;
 	static final int VALID = 2;
@@ -112,16 +115,13 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 		if ( v != null && v.isValid() )
 			return v;
 
+		cleanUp( 50 );
 		switch ( hints.getLoadingStrategy() )
 		{
 		case BLOCKING:
 			return getBlocking( entry );
 		case BUDGETED:
-			final int priority = hints.getQueuePriority();
-			final IoStatistics stats = CacheIoTiming.getIoStatistics();
-			final IoTimeBudget budget = stats.getIoTimeBudget();
-			final long timeLeft = budget.timeLeft( priority );
-			if ( timeLeft > 0 )
+			if ( estimatedBugdetTimeLeft( hints ) > 0 )
 				return getBudgeted( entry, hints );
 		case VOLATILE:
 			enqueue( entry, hints );
@@ -131,18 +131,27 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 		}
 	}
 
+	private long estimatedBugdetTimeLeft( final CacheHints hints )
+	{
+		final int priority = hints.getQueuePriority();
+		final IoStatistics stats = CacheIoTiming.getIoStatistics();
+		final IoTimeBudget budget = stats.getIoTimeBudget();
+		return budget.estimateTimeLeft( priority );
+	}
+
 	@Override
 	public V get( final K key, final VolatileLoader< ? extends V > loader, final CacheHints hints ) throws ExecutionException
 	{
 		/*
 		 * Get existing entry for key or create it.
 		 */
-		final Entry entry = map.computeIfAbsent( key, k -> new Entry( key, loader ) );
+		final Entry entry = map.computeIfAbsent( key, k -> new Entry( k, loader ) );
 
 		V v = entry.getValue();
 		if ( v != null && v.isValid() )
 			return v;
 
+		cleanUp( 50 );
 		switch ( hints.getLoadingStrategy() )
 		{
 		case BLOCKING:
@@ -159,8 +168,6 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 			break;
 		}
 
-		cleanUp( 10 );
-
 		if ( v == null )
 			return get( key, loader, hints );
 		else
@@ -298,6 +305,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 			V v = entry.getValue();
 			if ( v == null && entry.loaded != NOTLOADED )
 			{
+//				printEntryCollected( "map.remove getBudgeted 1", entry );
 				map.remove( entry.key, entry );
 				return null;
 			}
@@ -338,6 +346,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 				}
 				else
 				{
+//					printEntryCollected( "map.remove getBudgeted 2", entry );
 					map.remove( entry.key, entry );
 					return null;
 				}
@@ -354,6 +363,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 			final V v = entry.getValue();
 			if ( v == null && entry.loaded != NOTLOADED )
 			{
+//				printEntryCollected( "map.remove getBlocking 1", entry );
 				map.remove( entry.key, entry );
 				return null;
 			}
@@ -369,6 +379,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 			final V v = entry.getValue();
 			if ( v == null && entry.loaded != NOTLOADED )
 			{
+//				printEntryCollected( "map.remove getBlocking 2", entry );
 				map.remove( entry.key, entry );
 				return null;
 			}
@@ -395,4 +406,24 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements
 			fetchQueue.put( new FetchEntry( entry.key ), hints.getQueuePriority(), hints.isEnqueuToFront() );
 		}
 	}
+
+	/**
+	 * For debugging. Print stack trace when an Entry's value has been collected while we want
+	 * to load it.
+	 *
+	 * @param title
+	 * @param entry
+	 */
+	private synchronized void printEntryCollected( final String title, final Entry entry )
+	{
+		final String state = entry.loaded == 0
+				? "NOTLOADED"
+				: ( entry.loaded == 1
+						? "INVALID"
+						: ( entry.loaded == 2
+								? "VALID"
+								: "UNDEFINED" ) );
+		System.out.println( title + " entry.loaded = " + state );
+//		new Throwable().printStackTrace( System.out );
+	}
 }