On Thu, 2016-03-24 at 12:26 +0000, Harold Rosenberg wrote:
> 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
> 

I am glad it has helped. 

Feel free to raise JIRA with a feature request to make use of custom
SSLBufferManagementStrategy instances less cumbersome.

Oleg

> 
> 
> 
> 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
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org
> For additional commands, e-mail: httpclient-users-h...@hc.apache.org
> 



---------------------------------------------------------------------
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