ByteCache: Move all 16/32 byte users to SimpleByteCache;

increase SimpleByteCache default size.
This commit is contained in:
zzz
2012-09-02 12:31:08 +00:00
parent 4360284355
commit c48aca8d5c
10 changed files with 55 additions and 77 deletions

View File

@@ -21,8 +21,8 @@ import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.data.SessionKey;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
/**
* Wrapper for AES cypher operation using Cryptix's Rijndael implementation. Implements
@@ -38,8 +38,6 @@ public class CryptixAESEngine extends AESEngine {
// keys are now cached in the SessionKey objects
//private CryptixAESKeyCache _cache;
private static final ByteCache _prevCache = ByteCache.getInstance(16, 16);
/**** see comments for main() below
private static final boolean USE_SYSTEM_AES;
static {
@@ -166,10 +164,8 @@ public class CryptixAESEngine extends AESEngine {
int numblock = length / 16;
if (length % 16 != 0) numblock++;
ByteArray prevA = _prevCache.acquire();
byte prev[] = prevA.getData();
ByteArray curA = _prevCache.acquire();
byte cur[] = curA.getData();
byte prev[] = SimpleByteCache.acquire(16);
byte cur[] = SimpleByteCache.acquire(16);
System.arraycopy(iv, ivOffset, prev, 0, 16);
for (int x = 0; x < numblock; x++) {
@@ -190,8 +186,8 @@ public class CryptixAESEngine extends AESEngine {
}
*/
_prevCache.release(prevA);
_prevCache.release(curA);
SimpleByteCache.release(prev);
SimpleByteCache.release(cur);
}
/** encrypt exactly 16 bytes using the session key

View File

@@ -98,6 +98,11 @@ public class SDSCache<V extends SimpleDataStructure> {
}
/**
* WARNING - If the SDS is found in the cache, the passed-in
* byte array will be returned to the SimpleByteCache for reuse.
* Do NOT save a reference to the passed-in data, or use or modify it,
* after this call.
*
* @param data non-null, the byte array for the SimpleDataStructure
* @return the cached value if available, otherwise
* makes a new object and returns it

View File

@@ -13,22 +13,14 @@ import net.i2p.data.ByteArray;
* Cache the objects frequently used to reduce memory churn. The ByteArray
* should be held onto as long as the data referenced in it is needed.
*
* For small arrays where the management of valid bytes in ByteArray
* and prezeroing isn't required, use SimpleByteArray instead.
*
* Heap size control - survey of usage (April 2010) :
*
* <pre>
Size Max MaxMem From
16 16 256 CryptixAESEngine
16 32 512 BloomFilterIVValidator
16 64 1K UDP PacketBuilder
16 128 2K tunnel HopProcessor
16 128 2K tunnel TrivialPreprocessor
16 128 2K tunnel InboundEndpointProcessor
16 128 2K tunnel OutboundGatewayProcessor
32 64 2K UDP PacketBuilder
32 128 4K tunnel TrivialPreprocessor
1K 32 32K tunnel TrivialPreprocessor
1K 512 512K tunnel FragmentHandler
1K 512 512K I2NP TunnelDataMessage

View File

@@ -18,7 +18,7 @@ public final class SimpleByteCache {
private static final Map<Integer, SimpleByteCache> _caches = new ConcurrentHashMap(8);
private static final int DEFAULT_SIZE = 16;
private static final int DEFAULT_SIZE = 64;
/** 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;

View File

@@ -16,9 +16,9 @@ import net.i2p.data.Hash;
import net.i2p.data.RouterIdentity;
import net.i2p.data.SessionKey;
import net.i2p.data.Signature;
import net.i2p.util.ByteCache;
import net.i2p.util.Addresses;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
/**
* Big ol' class to do all our packet formatting. The UDPPackets generated are
@@ -102,9 +102,6 @@ class PacketBuilder {
private final Log _log;
private final UDPTransport _transport;
private static final ByteCache _ivCache = ByteCache.getInstance(64, UDPPacket.IV_SIZE);
private static final ByteCache _hmacCache = ByteCache.getInstance(64, Hash.HASH_LENGTH);
/**
* For debugging and stats only - does not go out on the wire.
* These are chosen to be higher than the highest I2NP message type,
@@ -607,12 +604,12 @@ class PacketBuilder {
// ok, now the full data is in there, but we also need to encrypt
// the signature, which means we need the IV
ByteArray iv = _ivCache.acquire();
_context.random().nextBytes(iv.getData());
byte[] iv = SimpleByteCache.acquire(UDPPacket.IV_SIZE);
_context.random().nextBytes(iv);
int encrWrite = Signature.SIGNATURE_BYTES + 8;
int sigBegin = off - encrWrite;
_context.aes().encrypt(data, sigBegin, data, sigBegin, state.getCipherKey(), iv.getData(), encrWrite);
_context.aes().encrypt(data, sigBegin, data, sigBegin, state.getCipherKey(), iv, encrWrite);
// pad up so we're on the encryption boundary
if ( (off % 16) != 0)
@@ -620,7 +617,7 @@ class PacketBuilder {
packet.getPacket().setLength(off);
authenticate(packet, ourIntroKey, ourIntroKey, iv);
setTo(packet, to, state.getSentPort());
_ivCache.release(iv);
SimpleByteCache.release(iv);
packet.setMessageType(TYPE_CREAT);
return packet;
}
@@ -1290,10 +1287,10 @@ class PacketBuilder {
* @param macKey key to generate the, er, MAC
*/
private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey) {
ByteArray iv = _ivCache.acquire();
_context.random().nextBytes(iv.getData());
byte[] iv = SimpleByteCache.acquire(UDPPacket.IV_SIZE);
_context.random().nextBytes(iv);
authenticate(packet, cipherKey, macKey, iv);
_ivCache.release(iv);
SimpleByteCache.release(iv);
}
/**
@@ -1308,38 +1305,38 @@ class PacketBuilder {
* @param macKey key to generate the, er, MAC
* @param iv IV to deliver
*/
private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey, ByteArray iv) {
private void authenticate(UDPPacket packet, SessionKey cipherKey, SessionKey macKey, byte[] iv) {
long before = System.currentTimeMillis();
int encryptOffset = packet.getPacket().getOffset() + UDPPacket.IV_SIZE + UDPPacket.MAC_SIZE;
int encryptSize = packet.getPacket().getLength() - UDPPacket.IV_SIZE - UDPPacket.MAC_SIZE - packet.getPacket().getOffset();
byte data[] = packet.getPacket().getData();
_context.aes().encrypt(data, encryptOffset, data, encryptOffset, cipherKey, iv.getData(), encryptSize);
_context.aes().encrypt(data, encryptOffset, data, encryptOffset, cipherKey, iv, encryptSize);
// ok, now we need to prepare things for the MAC, which requires reordering
int off = packet.getPacket().getOffset();
System.arraycopy(data, encryptOffset, data, off, encryptSize);
off += encryptSize;
System.arraycopy(iv.getData(), 0, data, off, UDPPacket.IV_SIZE);
System.arraycopy(iv, 0, data, off, UDPPacket.IV_SIZE);
off += UDPPacket.IV_SIZE;
DataHelper.toLong(data, off, 2, encryptSize ^ PROTOCOL_VERSION);
int hmacOff = packet.getPacket().getOffset();
int hmacLen = encryptSize + UDPPacket.IV_SIZE + 2;
//Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen);
ByteArray ba = _hmacCache.acquire();
_context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba.getData(), 0);
byte[] ba = SimpleByteCache.acquire(Hash.HASH_LENGTH);
_context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba, 0);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Authenticating " + packet.getPacket().getLength() +
"\nIV: " + Base64.encode(iv.getData()) +
"\nraw mac: " + Base64.encode(ba.getData()) +
"\nIV: " + Base64.encode(iv) +
"\nraw mac: " + Base64.encode(ba) +
"\nMAC key: " + macKey);
// ok, now lets put it back where it belongs...
System.arraycopy(data, hmacOff, data, encryptOffset, encryptSize);
//System.arraycopy(hmac.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
System.arraycopy(ba.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
System.arraycopy(iv.getData(), 0, data, hmacOff + UDPPacket.MAC_SIZE, UDPPacket.IV_SIZE);
_hmacCache.release(ba);
System.arraycopy(ba, 0, data, hmacOff, UDPPacket.MAC_SIZE);
System.arraycopy(iv, 0, data, hmacOff + UDPPacket.MAC_SIZE, UDPPacket.IV_SIZE);
SimpleByteCache.release(ba);
long timeToAuth = System.currentTimeMillis() - before;
_context.statManager().addRateData("udp.packetAuthTime", timeToAuth, timeToAuth);
if (timeToAuth > 100)

View File

@@ -5,7 +5,7 @@ import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.router.util.DecayingBloomFilter;
import net.i2p.router.util.DecayingHashSet;
import net.i2p.util.ByteCache;
import net.i2p.util.SimpleByteCache;
/**
* Manage the IV validation for all of the router's tunnels by way of a big
@@ -15,7 +15,6 @@ import net.i2p.util.ByteCache;
class BloomFilterIVValidator implements IVValidator {
private final RouterContext _context;
private final DecayingBloomFilter _filter;
private final ByteCache _ivXorCache = ByteCache.getInstance(32, HopProcessor.IV_LENGTH);
/**
* After 2*halflife, an entry is completely forgotten from the bloom filter.
@@ -57,10 +56,10 @@ class BloomFilterIVValidator implements IVValidator {
}
public boolean receiveIV(byte ivData[], int ivOffset, byte payload[], int payloadOffset) {
ByteArray buf = _ivXorCache.acquire();
DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf.getData(), 0, HopProcessor.IV_LENGTH);
boolean dup = _filter.add(buf.getData());
_ivXorCache.release(buf);
byte[] buf = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf, 0, HopProcessor.IV_LENGTH);
boolean dup = _filter.add(buf);
SimpleByteCache.release(buf);
if (dup) _context.statManager().addRateData("tunnel.duplicateIV", 1);
return !dup; // return true if it is OK, false if it isn't
}

View File

@@ -2,7 +2,6 @@ package net.i2p.router.tunnel;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
/**
@@ -29,7 +28,6 @@ class HopProcessor {
*/
static final boolean USE_DOUBLE_IV_ENCRYPTION = true;
static final int IV_LENGTH = 16;
private static final ByteCache _cache = ByteCache.getInstance(128, IV_LENGTH);
/** @deprecated unused */
public HopProcessor(I2PAppContext ctx, HopConfig config) {

View File

@@ -3,8 +3,8 @@ package net.i2p.router.tunnel;
import net.i2p.data.ByteArray;
import net.i2p.data.Hash;
import net.i2p.router.RouterContext;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
/**
* Receive the inbound tunnel message, removing all of the layers
@@ -21,7 +21,6 @@ class InboundEndpointProcessor {
private final IVValidator _validator;
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
/** @deprecated unused */
public InboundEndpointProcessor(RouterContext ctx, TunnelCreatorConfig cfg) {
@@ -54,8 +53,7 @@ class InboundEndpointProcessor {
return false;
}
ByteArray ba = _cache.acquire();
byte iv[] = ba.getData(); //new byte[HopProcessor.IV_LENGTH];
byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
System.arraycopy(orig, offset, iv, 0, iv.length);
//if (_config.getLength() > 1)
// _log.debug("IV at inbound endpoint before decrypt: " + Base64.encode(iv));
@@ -64,7 +62,7 @@ class InboundEndpointProcessor {
if (!ok) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid IV, dropping at IBEP " + _config);
_cache.release(ba);
SimpleByteCache.release(iv);
return false;
}
@@ -72,7 +70,7 @@ class InboundEndpointProcessor {
if (USE_ENCRYPTION)
decrypt(_context, _config, iv, orig, offset, length);
_cache.release(ba);
SimpleByteCache.release(iv);
if (_config.getLength() > 0) {
int rtt = 0; // dunno... may not be related to an rtt
@@ -91,8 +89,7 @@ class InboundEndpointProcessor {
*/
private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
//Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
ByteArray ba = _cache.acquire();
byte cur[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH]; // so we dont malloc
byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
for (int i = cfg.getLength()-2; i >= 0; i--) { // dont include the endpoint, since that is the creator
OutboundGatewayProcessor.decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
//if (log.shouldLog(Log.DEBUG)) {
@@ -100,7 +97,7 @@ class InboundEndpointProcessor {
//log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
//}
}
_cache.release(ba);
SimpleByteCache.release(cur);
}
}

View File

@@ -3,8 +3,8 @@ package net.i2p.router.tunnel;
import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
/**
* Turn the preprocessed tunnel data into something that can be delivered to the
@@ -18,7 +18,6 @@ class OutboundGatewayProcessor {
private final TunnelCreatorConfig _config;
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
public OutboundGatewayProcessor(I2PAppContext ctx, TunnelCreatorConfig cfg) {
_context = ctx;
@@ -35,8 +34,7 @@ class OutboundGatewayProcessor {
* @param length how much of orig can we write to (must be a multiple of 16).
*/
public void process(byte orig[], int offset, int length) {
ByteArray ba = _cache.acquire();
byte iv[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH];
byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
//_context.random().nextBytes(iv);
//System.arraycopy(iv, 0, orig, offset, HopProcessor.IV_LENGTH);
System.arraycopy(orig, offset, iv, 0, HopProcessor.IV_LENGTH);
@@ -49,7 +47,7 @@ class OutboundGatewayProcessor {
decrypt(_context, _config, iv, orig, offset, length);
if (_log.shouldLog(Log.DEBUG))
_log.debug("finished processing the preprocessed data");
_cache.release(ba);
SimpleByteCache.release(iv);
}
/**
@@ -58,8 +56,7 @@ class OutboundGatewayProcessor {
*/
private void decrypt(I2PAppContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
ByteArray ba = _cache.acquire();
byte cur[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH]; // so we dont malloc
byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
for (int i = cfg.getLength()-1; i >= 1; i--) { // dont include hop 0, since that is the creator
decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
if (log.shouldLog(Log.DEBUG)) {
@@ -67,7 +64,7 @@ class OutboundGatewayProcessor {
//log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
}
}
_cache.release(ba);
SimpleByteCache.release(cur);
}
/**

View File

@@ -9,6 +9,7 @@ import net.i2p.data.Hash;
import net.i2p.router.RouterContext;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
/**
* Do the simplest thing possible for preprocessing - for each message available,
@@ -33,9 +34,6 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
*/
protected static final ByteCache _dataCache = ByteCache.getInstance(32, PREPROCESSED_SIZE);
private static final ByteCache _ivCache = ByteCache.getInstance(128, IV_SIZE);
private static final ByteCache _hashCache = ByteCache.getInstance(128, Hash.HASH_LENGTH);
public TrivialPreprocessor(RouterContext ctx) {
_context = ctx;
_log = ctx.logManager().getLog(getClass());
@@ -63,16 +61,15 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
* @param fragmentLength fragments[0:fragmentLength] is used
*/
protected void preprocess(byte fragments[], int fragmentLength) {
ByteArray ivBuf = _ivCache.acquire();
byte iv[] = ivBuf.getData(); // new byte[IV_SIZE];
byte iv[] = SimpleByteCache.acquire(IV_SIZE);
_context.random().nextBytes(iv);
// payload ready, now H(instructions+payload+IV)
System.arraycopy(iv, 0, fragments, fragmentLength, IV_SIZE);
ByteArray hashBuf = _hashCache.acquire();
byte[] hashBuf = SimpleByteCache.acquire(Hash.HASH_LENGTH);
//Hash h = _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE);
_context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE, hashBuf.getData(), 0);
_context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE, hashBuf, 0);
//Hash h = _context.sha().calculateHash(target, 0, offset + IV_SIZE);
//_log.debug("before shift: " + Base64.encode(target));
@@ -91,12 +88,12 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
System.arraycopy(iv, 0, fragments, offset, IV_SIZE);
offset += IV_SIZE;
//System.arraycopy(h.getData(), 0, fragments, offset, 4);
System.arraycopy(hashBuf.getData(), 0, fragments, offset, 4);
System.arraycopy(hashBuf, 0, fragments, offset, 4);
offset += 4;
//_log.debug("before pad : " + Base64.encode(target));
_hashCache.release(hashBuf);
_ivCache.release(ivBuf);
SimpleByteCache.release(hashBuf);
SimpleByteCache.release(iv);
// fits in a single message, so may be smaller than the full size
int numPadBytes = PREPROCESSED_SIZE // max