diff --git a/core/java/src/net/i2p/data/SDSCache.java b/core/java/src/net/i2p/data/SDSCache.java
index 11b730664a0491e1504d00e04c416dfd2ff4a798..474e96479142c57289e6863fe3acc22634c6d5d6 100644
--- a/core/java/src/net/i2p/data/SDSCache.java
+++ b/core/java/src/net/i2p/data/SDSCache.java
@@ -45,8 +45,8 @@ public class SDSCache<V extends SimpleDataStructure> {
     //private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(SDSCache.class);
 
     private static final Class[] conArg = new Class[] { byte[].class };
-    private static final double MIN_FACTOR = 0.25;
-    private static final double MAX_FACTOR = 3.0;
+    private static final double MIN_FACTOR = 0.20;
+    private static final double MAX_FACTOR = 5.0;
     private static final double FACTOR;
     static {
         long maxMemory = Runtime.getRuntime().maxMemory();
diff --git a/core/java/src/net/i2p/util/SimpleByteCache.java b/core/java/src/net/i2p/util/SimpleByteCache.java
index 4aae936504acefac0ee8af59d62e54f2a6538c6f..01d116abea1c04eb23fc0d35ab8cce987c15d98d 100644
--- a/core/java/src/net/i2p/util/SimpleByteCache.java
+++ b/core/java/src/net/i2p/util/SimpleByteCache.java
@@ -2,6 +2,7 @@ package net.i2p.util;
 
 import java.util.Map;
 import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.LinkedBlockingQueue;
 
@@ -19,6 +20,9 @@ public final class SimpleByteCache {
 
     private static final int DEFAULT_SIZE = 16;
 
+    /** up to this, use ABQ to minimize object churn and for performance; above this, use LBQ for two locks */
+    private static final int MAX_FOR_ABQ = 64;
+
     /**
      * Get a cache responsible for arrays of the given size
      *
@@ -58,11 +62,11 @@ public final class SimpleByteCache {
     /** list of available and available entries */
     private Queue<byte[]> _available;
     private int _maxCached;
-    private int _entrySize;
+    private final int _entrySize;
     
     private SimpleByteCache(int maxCachedEntries, int entrySize) {
-        _available = new LinkedBlockingQueue(maxCachedEntries);
         _maxCached = maxCachedEntries;
+        _available = createQueue();
         _entrySize = entrySize;
     }
     
@@ -70,13 +74,23 @@ public final class SimpleByteCache {
         if (_maxCached >= maxCachedEntries) return;
         _maxCached = maxCachedEntries;
         // make a bigger one, move the cached items over
-        Queue<byte[]> newLBQ = new LinkedBlockingQueue(maxCachedEntries);
+        Queue<byte[]> newLBQ = createQueue();
         byte[] ba;
         while ((ba = _available.poll()) != null)
             newLBQ.offer(ba);
         _available = newLBQ;
     }
     
+    /**
+     *  @return LBQ or ABQ
+     *  @since 0.9.2
+     */
+    private Queue<byte[]> createQueue() {
+        if (_maxCached <= MAX_FOR_ABQ)
+            return new ArrayBlockingQueue(_maxCached);
+        return new LinkedBlockingQueue(_maxCached);
+    }
+
     /**
      * Get the next available array, either from the cache or a brand new one
      */