RFR: 8330108: Increase CipherInputStream buffer size

David Schlosnagle duke at openjdk.org
Sat Apr 13 01:28:48 UTC 2024


On Fri, 12 Apr 2024 15:34:01 GMT, Oli Gillespie <ogillespie at openjdk.org> wrote:

> Increase buffer size in CipherInputStream from 512 bytes to 8192 bytes.
> 
> I have seen applications where this small buffer size significantly reduces throughput, and I've even seen applications which use reflection to modify the buffer size to work around the issue.
> 
> Using the existing `AESGCMCipherInputStream` benchmark, we can see that 8192 performs better in all the explored cases than 512. Sometimes other sizes beat 8192, but it seems a good compromise of performance across encrypt/decrypt and memory usage, plus it's in line with other JDK classes like ChannelInputStream and FileInputStream.
> 
> ### Benchmark results
> 
> 
> make test TEST=micro:org.openjdk.bench.javax.crypto.full.AESGCMCipherInputStream
> 
> 
> 8192 wins substantially for encrypt of both data sizes, and wins noticeably for small decrypt data size, while remaining roughly equal for large decrypt data size (why are the error bars so wide there...?)
> 
> 
>  (benchmark)  (dataSize)        Score      Error  Units
> == buffer size = 512 (current) ==
>    decrypt         16384    41800.053 +-  674.761  ops/s
>    decrypt       1048576      219.218 +- 4509.696  ops/s
>    encrypt         16384    59481.957 +- 2297.546  ops/s
>    encrypt       1048576     1030.822 +-   48.273  ops/s
>    
> == buffer size = 8192 (this PR) ==
>    decrypt         16384    45023.512 +-  351.284  ops/s
>    decrypt       1048576      217.506 +- 4498.711  ops/s
>    encrypt         16384    71678.424 +- 1731.105  ops/s
>    encrypt       1048576     1562.457 +-   50.944  ops/s
> 
> == other candidates (rejected) ==
> buffer size = 128
>    decrypt         16384    36282.200 +- 3827.690  ops/s
>    decrypt       1048576      200.096 +- 3972.338  ops/s
>    encrypt         16384    38352.717 +- 5030.671  ops/s
>    encrypt       1048576      671.195 +-   84.134  ops/s
> buffer size = 2048
>    decrypt         16384    44411.579 +- 2452.429  ops/s
>    decrypt       1048576      224.036 +- 4582.988  ops/s
>    encrypt         16384    65907.313 +- 2678.562  ops/s
>    encrypt       1048576     1232.242 +-   53.233  ops/s
> buffer size = 32768
>    decrypt         16384    51004.362 +- 3147.855  ops/s
>    decrypt       1048576      205.818 +- 4233.473  ops/s
>    encrypt         16384    58716.428 +-  269.514  ops/s
>    encrypt       1048576     1564.075 +-   43.732  ops/s
> buffer size = 131702
>    decrypt         16384    32111.911 +-  766.159  ops/s
>    decrypt       1048576      247.852 +- 5533.972  ops/s
>    encrypt         16384    34678.424 +- 1869.548  ops/s
>    encrypt       1048576     ...

Should the buffer size be a configurable constructor parameter? This would allow consumers to adjust the buffer size to match their tradeoffs of memory vs throughput based on workload & available resources, and provide a bit of future-proofing as memory hierarchies expand over time (default 512 byte buffer is a few decades old). I imagine many folks are already wrapping `CipherInputStream` with a `BufferedInputStream` and this would allow folks to adjust the buffer size in `CipherInputStream` and remove the extra wrapper stream.

It would be nice to see a broader range of buffer sizes benchmarked across architectures to understand the tradeoffs and differences in throughput. For example, the default `InputStream` buffer size was increased from `8192` to `16384` in JDK-8299336 / https://github.com/openjdk/jdk/pull/11783 .

There are also a number of architecture specific tradeoffs related to cipher and intrinsics available that consumers may want to factor into buffer sizing.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/18763#issuecomment-2052872052



More information about the security-dev mailing list