Optimize native handling further.

We now try to work within the boundaries given by the native. In the
case of Java natives, we work with byte arrays. With natives, always use
direct buffers.

However, the numbers do favor the natives, since they work with direct
byte buffers, without any copying. For the most part, this commit is
intended to improve the lives of Velocity users on Windows.
This commit is contained in:
Andrew Steinborn
2018-12-30 06:16:04 -05:00
parent 095a478440
commit 8588e7f1fe
10 changed files with 121 additions and 57 deletions

View File

@@ -9,7 +9,9 @@ import com.velocitypowered.natives.util.Natives;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.io.IOException;
import java.util.Random;
import java.util.function.Supplier;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import org.junit.jupiter.api.BeforeAll;
@@ -18,9 +20,12 @@ import org.junit.jupiter.api.condition.EnabledOnOs;
class VelocityCompressorTest {
private static byte[] TEST_DATA = new byte[1 << 14];
@BeforeAll
static void checkNatives() {
static void checkNatives() throws IOException {
Natives.compress.getLoadedVariant();
new Random(1).nextBytes(TEST_DATA);
}
@Test
@@ -31,25 +36,30 @@ class VelocityCompressorTest {
compressor.dispose();
fail("Loaded regular compressor");
}
check(compressor);
check(compressor, () -> Unpooled.directBuffer(TEST_DATA.length));
}
@Test
void javaIntegrityCheck() throws DataFormatException {
void javaIntegrityCheckDirect() throws DataFormatException {
VelocityCompressor compressor = JavaVelocityCompressor.FACTORY
.create(Deflater.DEFAULT_COMPRESSION);
check(compressor);
check(compressor, () -> Unpooled.directBuffer(TEST_DATA.length));
}
private void check(VelocityCompressor compressor) throws DataFormatException {
ByteBuf source = Unpooled.directBuffer();
ByteBuf dest = Unpooled.directBuffer();
ByteBuf decompressed = Unpooled.directBuffer();
@Test
void javaIntegrityCheckHeap() throws DataFormatException {
VelocityCompressor compressor = JavaVelocityCompressor.FACTORY
.create(Deflater.DEFAULT_COMPRESSION);
check(compressor, () -> Unpooled.buffer(TEST_DATA.length));
}
Random random = new Random(1);
byte[] randomBytes = new byte[1 << 16];
random.nextBytes(randomBytes);
source.writeBytes(randomBytes);
private void check(VelocityCompressor compressor, Supplier<ByteBuf> bufSupplier)
throws DataFormatException {
ByteBuf source = bufSupplier.get();
ByteBuf dest = bufSupplier.get();
ByteBuf decompressed = bufSupplier.get();
source.writeBytes(TEST_DATA);
try {
compressor.deflate(source, dest);

View File

@@ -9,6 +9,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.security.GeneralSecurityException;
import java.util.Random;
import java.util.function.Supplier;
import javax.crypto.spec.SecretKeySpec;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
@@ -16,11 +17,16 @@ import org.junit.jupiter.api.Test;
class VelocityCipherTest {
private static final int ENCRYPT_DATA_SIZE = 1 << 16;
private static final int ENCRYPT_DATA_SIZE = 1 << 14;
private static byte[] TEST_DATA = new byte[ENCRYPT_DATA_SIZE];;
private static final byte[] AES_KEY = new byte[16];
@BeforeAll
static void checkNatives() {
Natives.cipher.getLoadedVariant();
Random random = new Random(1);
random.nextBytes(TEST_DATA);
random.nextBytes(AES_KEY);
}
@Test
@@ -30,30 +36,30 @@ class VelocityCipherTest {
if (factory == JavaVelocityCipher.FACTORY) {
fail("Loaded regular cipher");
}
check(factory);
check(factory, Unpooled::directBuffer);
}
@Test
void javaIntegrityCheck() throws GeneralSecurityException {
check(JavaVelocityCipher.FACTORY);
void javaIntegrityCheckDirect() throws GeneralSecurityException {
check(JavaVelocityCipher.FACTORY, Unpooled::directBuffer);
}
private void check(VelocityCipherFactory factory) throws GeneralSecurityException {
@Test
void javaIntegrityCheckHeap() throws GeneralSecurityException {
check(JavaVelocityCipher.FACTORY, Unpooled::buffer);
}
private void check(VelocityCipherFactory factory, Supplier<ByteBuf> bufSupplier)
throws GeneralSecurityException {
// Generate a random 16-byte key.
Random random = new Random(1);
byte[] key = new byte[16];
random.nextBytes(key);
VelocityCipher decrypt = factory.forDecryption(new SecretKeySpec(AES_KEY, "AES"));
VelocityCipher encrypt = factory.forEncryption(new SecretKeySpec(AES_KEY, "AES"));
VelocityCipher decrypt = factory.forDecryption(new SecretKeySpec(key, "AES"));
VelocityCipher encrypt = factory.forEncryption(new SecretKeySpec(key, "AES"));
ByteBuf source = bufSupplier.get();
ByteBuf dest = bufSupplier.get();
ByteBuf decryptionBuf = bufSupplier.get();
ByteBuf source = Unpooled.directBuffer(ENCRYPT_DATA_SIZE);
ByteBuf dest = Unpooled.directBuffer(ENCRYPT_DATA_SIZE);
ByteBuf decryptionBuf = Unpooled.directBuffer(ENCRYPT_DATA_SIZE);
byte[] randomBytes = new byte[ENCRYPT_DATA_SIZE];
random.nextBytes(randomBytes);
source.writeBytes(randomBytes);
source.writeBytes(TEST_DATA);
try {
encrypt.process(source, dest);