Refactor SslHandler internals to always use heap buffers for JDK SSLE… (#9696)
Motivation: We should aim to always use heap buffers when using the JDK SSLEngine for now as it wants to operate on byte[] and so will do internal memory copies if a non heap buffer is used. Beside this it will always return BUFFER_OVERFLOW when a smaller buffer then 16kb is used when calling wrap(...) (even if a very small amount of bytes should be encrypted). This can lead to excercive direct memory usage and pressure for no good reason. Modifications: Refactor internals of SslHandler to ensure we use heap buffers for the JDK SSLEngine impelementation Result: Less direct memory usage when JDK SSLEngine implementation is used
This commit is contained in:
parent
67e3ddb568
commit
7150b42a56
@ -210,14 +210,10 @@ public class SslHandler extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int getPacketBufferSize(SslHandler handler) {
|
ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
|
||||||
return ((ReferenceCountedOpenSslEngine) handler.engine).maxEncryptedPacketLength0();
|
int pendingBytes, int numComponents) {
|
||||||
}
|
return allocator.directBuffer(((ReferenceCountedOpenSslEngine) handler.engine)
|
||||||
|
.calculateMaxLengthForWrap(pendingBytes, numComponents));
|
||||||
@Override
|
|
||||||
int calculateWrapBufferCapacity(SslHandler handler, int pendingBytes, int numComponents) {
|
|
||||||
return ((ReferenceCountedOpenSslEngine) handler.engine).calculateMaxLengthForWrap(pendingBytes,
|
|
||||||
numComponents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -259,8 +255,10 @@ public class SslHandler extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int calculateWrapBufferCapacity(SslHandler handler, int pendingBytes, int numComponents) {
|
ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
|
||||||
return ((ConscryptAlpnSslEngine) handler.engine).calculateOutNetBufSize(pendingBytes, numComponents);
|
int pendingBytes, int numComponents) {
|
||||||
|
return allocator.directBuffer(
|
||||||
|
((ConscryptAlpnSslEngine) handler.engine).calculateOutNetBufSize(pendingBytes, numComponents));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -302,8 +300,15 @@ public class SslHandler extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int calculateWrapBufferCapacity(SslHandler handler, int pendingBytes, int numComponents) {
|
ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
|
||||||
return handler.engine.getSession().getPacketBufferSize();
|
int pendingBytes, int numComponents) {
|
||||||
|
// As for the JDK SSLEngine we always need to allocate buffers of the size required by the SSLEngine
|
||||||
|
// (normally ~16KB). This is required even if the amount of data to encrypt is very small. Use heap
|
||||||
|
// buffers to reduce the native memory usage.
|
||||||
|
//
|
||||||
|
// Beside this the JDK SSLEngine also (as of today) will do an extra heap to direct buffer copy
|
||||||
|
// if a direct buffer is used as its internals operate on byte[].
|
||||||
|
return allocator.heapBuffer(handler.engine.getSession().getPacketBufferSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -327,23 +332,21 @@ public class SslHandler extends ByteToMessageDecoder {
|
|||||||
this.cumulator = cumulator;
|
this.cumulator = cumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getPacketBufferSize(SslHandler handler) {
|
|
||||||
return handler.engine.getSession().getPacketBufferSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int readerIndex, int len, ByteBuf out)
|
abstract SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int readerIndex, int len, ByteBuf out)
|
||||||
throws SSLException;
|
throws SSLException;
|
||||||
|
|
||||||
abstract int calculateWrapBufferCapacity(SslHandler handler, int pendingBytes, int numComponents);
|
|
||||||
|
|
||||||
abstract int calculatePendingData(SslHandler handler, int guess);
|
abstract int calculatePendingData(SslHandler handler, int guess);
|
||||||
|
|
||||||
abstract boolean jdkCompatibilityMode(SSLEngine engine);
|
abstract boolean jdkCompatibilityMode(SSLEngine engine);
|
||||||
|
|
||||||
|
abstract ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
|
||||||
|
int pendingBytes, int numComponents);
|
||||||
|
|
||||||
// BEGIN Platform-dependent flags
|
// BEGIN Platform-dependent flags
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code true} if and only if {@link SSLEngine} expects a direct buffer.
|
* {@code true} if and only if {@link SSLEngine} expects a direct buffer and so if a heap buffer
|
||||||
|
* is given will make an extra memory copy.
|
||||||
*/
|
*/
|
||||||
final boolean wantsDirectBuffer;
|
final boolean wantsDirectBuffer;
|
||||||
|
|
||||||
@ -2103,7 +2106,7 @@ public class SslHandler extends ByteToMessageDecoder {
|
|||||||
* the specified amount of pending bytes.
|
* the specified amount of pending bytes.
|
||||||
*/
|
*/
|
||||||
private ByteBuf allocateOutNetBuf(ChannelHandlerContext ctx, int pendingBytes, int numComponents) {
|
private ByteBuf allocateOutNetBuf(ChannelHandlerContext ctx, int pendingBytes, int numComponents) {
|
||||||
return allocate(ctx, engineType.calculateWrapBufferCapacity(this, pendingBytes, numComponents));
|
return engineType.allocateWrapBuffer(this, ctx.alloc(), pendingBytes, numComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user