Using the ReleasableSSLBufferManagementStrategy gave a nice improvement.  For 
the same run with 7500 simulated users, the change reduced the average live 
data in the heap after a full GC from 3.2GB to about 1.5GB.  The amount of live 
data is still proportional to the number of connections (about 3GB of live data 
for a run with 15,000 simulated users), but that is to be expected.

Thanks for the help.

Hal




On 3/23/16, 3:59 PM, "Oleg Kalnichevski" <ol...@apache.org> wrote:

>On Wed, 2016-03-23 at 18:54 +0000, Harold Rosenberg wrote:
>> I am seeing unexpected behavior in the memory usage of a program that uses 
>> the Async Http Client.  The issue arises when I switch from using 
>> exclusively HTTP connections to exclusively HTTPS connections.  In the 
>> latter case, there is a large amount of memory used for byte arrays that 
>> seem to be related to SSL processing, and that aren’t ever cleaned up by 
>> garbage collection.
>> 
>> My question is whether this is expected due to differences between SSL and 
>> non-SSL processing, or whether I am failing to properly clean up my SSL 
>> connections.
>> 
>> The program is a workload driver for a performance benchmark.  It simulates 
>> user activity to a web service.  Each simulated user has about four active 
>> connections to the service.  Normally the connections are all over SSL 
>> (really TLS), but for testing purposes there is a switch to use only non-SSL 
>> connections.  The configuration of the HTTP client is identical for in both 
>> cases.
>> 
>> I gathered garbage-collection data with and without TLS for runs with 7,500 
>> simulated users, which would average about 30,000 active connections.  A 
>> user would be active for about five minutes, at which point the they log out 
>> and a new user logs in.  While the user is logged in the connections will 
>> occasionally be idle and thus closed due to keepalive timeout.  The runs 
>> were two hours long and the data was collected during a steady-state.  Data 
>> is generated in the heap at about the same rate in both cases, but when 
>> running with HTTPS there is about 3.2GB of live data left in the heap after 
>> a full garbage-collection, while with just HTTP there is only about 890MB.  
>> The amount of live data in the heap doesn’t grow once it reaches the 3.2GB 
>> mark, so it isn’t a memory leak, but it is definitely proportional to the 
>> number of active connections.  When I do the same run with 15,000 users, at 
>> steady-state the live data in the heap after a full GC is about 6.4GB.
>> 
>> Of the 3.2GB of live data, about 2.8GB is in 876,041 instances of byte[].  
>> Almost all of the instances seem to be related to SSL processing.  Here is 
>> the path to the nearest GC root for a few random instances:
>> 
>
>Hi Harold,
>
>Could you try using ReleasableSSLBufferManagementStrategy instead of
>default PermanentSSLBufferManagementStrategy?
>
>---
>DefaultHostnameVerifier hostnameVerifier = new 
>DefaultHostnameVerifier(PublicSuffixMatcherLoader.getDefault());
>Registry<SchemeIOSessionStrategy> registry = 
>RegistryBuilder.<SchemeIOSessionStrategy>create()
>        .register("http", NoopIOSessionStrategy.INSTANCE)
>        .register("https", new SchemeIOSessionStrategy() {
>            @Override
>            public boolean isLayeringRequired() {
>                return true;
>            }
>
>            @Override
>            public IOSession upgrade(final HttpHost host, final IOSession 
> iosession) throws IOException {
>                final SSLIOSession ssliosession = new SSLIOSession(
>                        iosession,
>                        SSLMode.CLIENT,
>                        host,
>                        SSLContexts.createSystemDefault(),
>                        new SSLSetupHandler() {
>
>                            @Override
>                            public void initalize(final SSLEngine sslengine) 
> throws SSLException {
>                            }
>
>                            @Override
>                            public void verify(
>                                    final IOSession iosession,
>                                    final SSLSession sslsession) throws 
> SSLException {
>                                if 
> (!hostnameVerifier.verify(host.getHostName(), sslsession)) {
>                                    final Certificate[] certs = 
> sslsession.getPeerCertificates();
>                                    final X509Certificate x509 = 
> (X509Certificate) certs[0];
>                                    final X500Principal x500Principal = 
> x509.getSubjectX500Principal();
>                                    throw new SSLPeerUnverifiedException("Host 
> name '" + host.getHostName() + "' does not match " +
>                                            "the certificate subject provided 
> by the peer (" + x500Principal.toString() + ")");
>                                }
>                            }
>
>                        },
>                        new ReleasableSSLBufferManagementStrategy());
>                iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession);
>                ssliosession.initialize();
>                return ssliosession;
>            }
>        })
>        .build();
>
>ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor();
>PoolingNHttpClientConnectionManager cm = new 
>PoolingNHttpClientConnectionManager(ioReactor, registry);
>CloseableHttpAsyncClient httpclient = HttpAsyncClients.createMinimal(cm);
>try {
>    httpclient.start();
>    HttpGet request = new 
> HttpGet("https://urldefense.proofpoint.com/v2/url?u=https-3A__verisign.com_&d=BQIDaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=9uYCHvq1QDKcMAIXCt6iT2etdTpbRn0toGoRKE6QxRo&m=HkvNV6bDDfPghsn_MF5SgU7KlMhzmAGjcfgAmviJCSs&s=w1-QtI1DaVx22Oo8UumpY0uvEblsK5t55MihZ_UwmPM&e=
>  ");
>    Future<HttpResponse> future = httpclient.execute(request, null);
>    HttpResponse response = future.get();
>    System.out.println("Response: " + response.getStatusLine());
>    System.out.println("Shutting down");
>} finally {
>    httpclient.close();
>}
>System.out.println("Done");
>---
>
>Oleg
>
>> this     - value: byte[] #483799
>>  <- hb     - class: java.nio.HeapByteBuffer, value: byte[] #483799
>>   <- buffer     - class: 
>> org.apache.http.nio.reactor.ssl.PermanentSSLBufferManagementStrategy$InternalBuffer,
>>  value: java.nio.HeapByteBuffer #89456
>>    <- outPlain     - class: org.apache.http.nio.reactor.ssl.SSLIOSession, 
>> value: 
>> org.apache.http.nio.reactor.ssl.PermanentSSLBufferManagementStrategy$InternalBuffer
>>  #59632
>>     <- bufferStatus     - class: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl, value: 
>> org.apache.http.nio.reactor.ssl.SSLIOSession #14910
>>      <- attachment     - class: sun.nio.ch.SelectionKeyImpl, value: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl #14910
>>       <- value     - class: java.util.HashMap$Entry, value: 
>> sun.nio.ch.SelectionKeyImpl #14910
>>        <- [355]     - class: java.util.HashMap$Entry[], value: 
>> java.util.HashMap$Entry #197065
>>         <- table     - class: java.util.HashMap, value: 
>> java.util.HashMap$Entry[] #4612
>>          <- fdToKey (Java frame)     - class: sun.nio.ch.EPollSelectorImpl, 
>> value: java.util.HashMap #10016
>> 
>> this     - value: byte[] #60139
>>  <- key     - class: 
>> com.sun.crypto.provider.TlsMasterSecretGenerator$TlsMasterSecretKey, value: 
>> byte[] #60139
>>   <- masterSecret     - class: sun.security.ssl.SSLSessionImpl, value: 
>> com.sun.crypto.provider.TlsMasterSecretGenerator$TlsMasterSecretKey #4827
>>    <- sess     - class: sun.security.ssl.SSLEngineImpl, value: 
>> sun.security.ssl.SSLSessionImpl #4829
>>     <- sslEngine     - class: org.apache.http.nio.reactor.ssl.SSLIOSession, 
>> value: sun.security.ssl.SSLEngineImpl #20572
>>      <- bufferStatus     - class: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl, value: 
>> org.apache.http.nio.reactor.ssl.SSLIOSession #20572
>>       <- attachment     - class: sun.nio.ch.SelectionKeyImpl, value: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl #20572
>>        <- value     - class: java.util.HashMap$Entry, value: 
>> sun.nio.ch.SelectionKeyImpl #20572
>>         <- [1182]     - class: java.util.HashMap$Entry[], value: 
>> java.util.HashMap$Entry #254234
>>          <- table     - class: java.util.HashMap, value: 
>> java.util.HashMap$Entry[] #6977
>>           <- fdToKey (Java frame)     - class: sun.nio.ch.EPollSelectorImpl, 
>> value: java.util.HashMap #9595
>> 
>> this     - value: byte[] #71913
>>  <- iv     - class: com.sun.crypto.provider.CipherBlockChaining, value: 
>> byte[] #71913
>>   <- cipher     - class: com.sun.crypto.provider.CipherCore, value: 
>> com.sun.crypto.provider.CipherBlockChaining #3709
>>    <- core     - class: com.sun.crypto.provider.AESCipher$General, value: 
>> com.sun.crypto.provider.CipherCore #3709
>>     <- spi     - class: javax.crypto.Cipher, value: 
>> com.sun.crypto.provider.AESCipher$General #3709
>>      <- cipher     - class: sun.security.ssl.CipherBox, value: 
>> javax.crypto.Cipher #3709
>>       <- readCipher     - class: sun.security.ssl.SSLEngineImpl, value: 
>> sun.security.ssl.CipherBox #3710
>>        <- sslEngine     - class: 
>> org.apache.http.nio.reactor.ssl.SSLIOSession, value: 
>> sun.security.ssl.SSLEngineImpl #1855
>>         <- bufferStatus     - class: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl, value: 
>> org.apache.http.nio.reactor.ssl.SSLIOSession #1855
>>          <- key     - class: java.util.HashMap$Entry, value: 
>> org.apache.http.impl.nio.reactor.IOSessionImpl #1855
>>           <- [4000]     - class: java.util.HashMap$Entry[], value: 
>> java.util.HashMap$Entry #71715
>>            <- table     - class: java.util.HashMap, value: 
>> java.util.HashMap$Entry[] #24138
>>             <- map     - class: java.util.HashSet, value: java.util.HashMap 
>> #8449
>>              <- c     - class: java.util.Collections$SynchronizedSet, value: 
>> java.util.HashSet #3312
>>               <- sessions (Java frame)     - class: 
>> org.apache.http.impl.nio.reactor.BaseIOReactor, value: 
>> java.util.Collections$SynchronizedSet #6
>> 
>> I can give more details about the configuration of the HTTP Client and the 
>> SSL sessions if it would be helpful, but I don’t want to give too much info 
>> if this is expected behavior.
>> 
>> Any advice would be appreciated.
>> 
>> Thanks,
>> 
>> Hal
>> 
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org
>For additional commands, e-mail: httpclient-users-h...@hc.apache.org
>

Reply via email to