Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8293464

x64 30% performance regression in TLS performance between Java 17 and 19 w/ GCM

XMLWordPrintable

    • 19
    • b01
    • x86_64
    • linux

      ADDITIONAL SYSTEM INFORMATION :
      AMD64 AWS host on recent Ubuntu.

      A DESCRIPTION OF THE PROBLEM :
      I have an Undertow powered webserver.
      This uses the SSLEngine mechanism of using TLS (and there are no obvious problems in how it uses TLS). I'm using an Apache HttpClient 5 client, again with no obvious misconfigurations.

      What I am observing is that between Java 17 and Java 19, TLS performance is considerably degraded on x64 targets with AES-GCM ciphersuites. Switching my application from Java 17 to 19 represents a 30% drop in throughput in the testing configuration (from 1.8GB/sec to 1.2GB/sec).

      From basic profiling, it appears a significant contributing factor is that upon performing an SSLEngine.wrap() call, the underlying Cipher will allocate and copy data.

      Specifically:
      SSLEngineImpl.wrap(ByteBuffer[] srcs, int srcsOffset, int srcsLength,
      ByteBuffer[] dsts, int dstsOffset, int dstsLength)
      calls through to writeRecord, and through encode to
      SSLEngineOutputRecord.encode(ByteBuffer[], int, int, ByteBuffer), which copies the src bytebuffers into the dst bytebuffer.
      This then calls encrypt, t13Encrypt, and then T13GcmWriteCipherGenerator.GcmWriteCipher.encrypt, which eventually calls GaloisCounterMode.doFinal. This now takes an src and dst bytebuffer, and if in overlapDetection it copies the buffers. Due to the codepath taken through the above classes, this is guaranteed to always copy.

      This means that in Java 19 via SSLEngine, TLS with GCM is guaranteed to (for N bytes written) allocate at least N bytes of memory, which was not previously the case.

      This is additionally the case on the read side, though via a different mechanic (through AppInputStream

      I don't know if these are the sole cause of the performance drops, but certainly it would lead to guaranteed GC pressure and represents a regression from Java 17 to 19.

      REGRESSION : Last worked in version 17.0.4.1

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      - Write a short benchmark which uses Java's SSL primitives to implement SSL over a socket. Perhaps use Undertow and HttpClient to set up this connection, though this is not necessary. I have such a benchmark but it uses our internal libraries for doing this. I attempted to make an open source version but figured that there'd be enough limitations (e.g. generating key material) that writing the benchmark is not the hard bit. It's likely that there are already TLS performance benchmarks in Java, I just haven't found them yet.
      - Run benchmark against Java 17 and Java 19, profiling with Java Flight Recorder.
      - Observe that Java 19 has considerably degraded performance as compared to 17. Observe that in Java flight recorder, one can see that memory allocation is extremely high in comparison to Java 17's edition.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Java 19 TLS is no slower than Java 17.
      ACTUAL -
      Java 19 TLS is much slower and causes considerable GC pressure.

      FREQUENCY : always


            ascarpino Anthony Scarpino
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: