RFR: 8344144: AES/CBC slow at big payloads
Volodymyr Paprotski
vpaprotski at openjdk.org
Wed Nov 13 21:19:57 UTC 2024
On Wed, 13 Nov 2024 21:14:58 GMT, Volodymyr Paprotski <vpaprotski at openjdk.org> wrote:
> Measuring throughput with JMH parameters `-f 1 -i 2 -wi 3 -r 20 -w 30 -p algorithm=AES/CBC/NoPadding -p dataSize=30000000 -p provider=SunJCE -p keyLength=128 org.openjdk.bench.javax.crypto.full.AESBench`
>
> Before:
>
> Benchmark (algorithm) (dataSize) (keyLength) (provider) Mode Cnt Score Error Units
> AESBench.decrypt AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 25.383 ops/s
> AESBench.decrypt2 AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 32.230 ops/s
> AESBench.encrypt AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 20.489 ops/s
> AESBench.encrypt2 AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 21.383 ops/s
>
>
> After:
>
> Benchmark (algorithm) (dataSize) (keyLength) (provider) Mode Cnt Score Error Units
> AESBench.decrypt AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 215.144 ops/s
> AESBench.decrypt2 AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 411.265 ops/s
> AESBench.encrypt AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 64.341 ops/s
> AESBench.encrypt2 AES/CBC/NoPadding 30000000 128 SunJCE thrpt 2 73.114 ops/s
>
>
> I have not deterministically proven why chunking works: before the change, the CBC intrinsic is not being used; and after chunking, it is. There is quite a bit of GC activity in the default AESBench, so `encrypt2/decrypt2` versions isolate just crypto (see comment below).
If you are trying to reproduce results, the AESBench was modified for large payloads as follows (encrypt2/decrypt2 cause less GC churn by using existing memory):
diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java b/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java
index 7e1eecdace4..93cf9a1d30f 100644
--- a/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java
@@ -25,6 +25,9 @@
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.infra.Blackhole;
+import java.security.GeneralSecurityException;
+import org.openjdk.jmh.annotations.Fork;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@@ -36,9 +39,10 @@
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;
+ at Fork(jvmArgsAppend = {"-Xms20g", "-Xmx20g", "-XX:+UseZGC"})
public class AESBench extends CryptoBase {
- public static final int SET_SIZE = 128;
+ public static final int SET_SIZE = 8;
@Param({"AES/ECB/NoPadding", "AES/ECB/PKCS5Padding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"})
private String algorithm;
@@ -53,6 +57,7 @@ public class AESBench extends CryptoBase {
byte[][] encryptedData;
private Cipher encryptCipher;
private Cipher decryptCipher;
+ private byte[] outBuffer;
int index = 0;
@Setup
@@ -66,6 +71,7 @@ public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, Inv
decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
data = fillRandom(new byte[SET_SIZE][dataSize]);
encryptedData = fillEncrypted(data, encryptCipher);
+ outBuffer = new byte[dataSize + 128]; // extra space for tag, etc
}
@Benchmark
@@ -75,6 +81,13 @@ public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
return encryptCipher.doFinal(d);
}
+ @Benchmark
+ public void encrypt2(Blackhole bh) throws GeneralSecurityException {
+ byte[] d = data[index];
+ index = (index +1) % SET_SIZE;
+ bh.consume(encryptCipher.doFinal(d, 0, d.length, outBuffer));
+ }
+
@Benchmark
public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
byte[] e = encryptedData[index];
@@ -82,4 +95,11 @@ public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
return decryptCipher.doFinal(e);
}
+ @Benchmark
+ public void decrypt2(Blackhole bh) throws GeneralSecurityException {
+ byte[] e = encryptedData[index];
+ index = (index +1) % SET_SIZE;
+ bh.consume(decryptCipher.doFinal(e, 0, e.length, outBuffer));
+ }
+
}
-------------
PR Comment: https://git.openjdk.org/jdk/pull/22086#issuecomment-2474800106
More information about the security-dev
mailing list