users@grizzly.java.net

Re: Upload a large file without oom with Grizzly

From: Ryan Lubke <ryan.lubke_at_oracle.com>
Date: Wed, 11 Sep 2013 12:38:05 -0700

Okay, I've committed another set of refactorings to the
FeedableBodyGenerator.

For your use case, you should extend FeedableBodyGenerator.SimpleFeeder.

Let me know if you run into issues.



Sébastien Lorber wrote:
> Yes I think it would, so that I can feed the queue at once
>
> One thread will be locked during the feeding for nothing but it's not
> a real problem in my usecase.
>
>
> 2013/9/10 Ryan Lubke <ryan.lubke_at_oracle.com
> <mailto:ryan.lubke_at_oracle.com>>
>
> Would having a different listener that will be notified once async
> transferring has been started work better for you?
>
> Something like:
>
> onAsyncTransferInitiated() {
> // invoke your feed method
> }
>
> ?
>
>
>
> Sébastien Lorber wrote:
>> Unfortunatly I won't be able to use the Feeder non-blocking stuff
>> for now, because of how the multipart request in handled in AHC
>>
>>
>> Here's my feeding method:
>>
>> public void feed() throws IOException {
>> Part[] partsArray = parts.toArray(new Part[parts.size()]);
>> try ( OutputStream outputStream = createFeedingOutputStream() ) {
>> Part.sendParts(outputStream,partsArray,multipartBoundary);
>> } catch (Exception e) {
>> throw new IllegalStateException("Unable to feed the
>> FeedableBodyGenerator",e);
>> }
>> }
>>
>>
>> As you can see, the multipart Parts array can only be pushed to
>> the OutputStream, I don't have any way to "pull" the data when
>> the canFeed() method is triggered.
>>
>>
>> But I've seen that there's
>> a com.ning.http.multipart.MultipartBody#read that seems to
>> provide a memory efficient way to pull data from a Multipart body...
>>
>> Should see what I come up with this
>>
>>
>> 2013/9/10 Sébastien Lorber <lorber.sebastien_at_gmail.com
>> <mailto:lorber.sebastien_at_gmail.com>>
>>
>> It seems the Feeder is highly recommended but not mandatory
>> so I tried without.
>>
>> With my existing code it seems there is a synchronization
>> problem.
>>
>>
>> The feeding threads get locked to the prematureFeed.get();
>>
>> So the Grizzly kernel threads are unable to acquire the lock
>> required to enter the initializeAsynchronousTransfer method
>>
>>
>>
>> Will try with an implementation of Feeder
>>
>>
>>
>> 2013/9/10 Sébastien Lorber <lorber.sebastien_at_gmail.com
>> <mailto:lorber.sebastien_at_gmail.com>>
>>
>> Hmmm it seems I have a problem with one of your maven
>> plugins. I'll try to bypass it, but for info:
>>
>> ➜ ahc2 git:(ahc-1.7.x) mvn clean install
>> [WARNING]
>> [WARNING] Some problems were encountered while building
>> the effective settings
>> [WARNING]
>> 'profiles.profile[default].repositories.repository.id
>> <http://repositories.repository.id>' must be unique but
>> found duplicate repository with id
>> fullsix-maven-repository @ /home/slorber/.m2/settings.xml
>> [WARNING]
>> [INFO] Scanning for projects...
>> [INFO]
>> [INFO]
>> ------------------------------------------------------------------------
>> [INFO] Building Asynchronous Http Client 1.7.20-SNAPSHOT
>> [INFO]
>> ------------------------------------------------------------------------
>> [INFO]
>> [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean)
>> @ async-http-client ---
>> [INFO]
>> [INFO] --- maven-enforcer-plugin:1.0-beta-1:enforce
>> (enforce-maven) @ async-http-client ---
>> [INFO]
>> [INFO] --- maven-enforcer-plugin:1.0-beta-1:enforce
>> (enforce-versions) @ async-http-client ---
>> [INFO]
>> [INFO] --- maven-resources-plugin:2.4.3:resources
>> (default-resources) @ async-http-client ---
>> [INFO] Using 'UTF-8' encoding to copy filtered resources.
>> [INFO] skip non existing resourceDirectory
>> /home/slorber/Bureau/ahc2/src/main/resources
>> [INFO]
>> [INFO] --- maven-compiler-plugin:2.3.2:compile
>> (default-compile) @ async-http-client ---
>> [INFO] Compiling 158 source files to
>> /home/slorber/Bureau/ahc2/target/classes
>> [INFO]
>> *[INFO] --- animal-sniffer-maven-plugin:1.6:check
>> (check-java-1.5-compat) @ async-http-client ---*
>> *[INFO] Checking unresolved references to
>> org.codehaus.mojo.signature:java15:1.0*
>> *[ERROR] Undefined reference:
>> java/io/IOException.<init>(Ljava/lang/Throwable;)V in
>> /home/slorber/Bureau/ahc2/target/classes/com/ning/http/client/providers/grizzly/FeedableBodyGenerator.class*
>> [INFO]
>> ------------------------------------------------------------------------
>> [INFO] BUILD FAILURE
>> [INFO]
>> ------------------------------------------------------------------------
>> [INFO] Total time: 8.747s
>> [INFO] Finished at: Tue Sep 10 11:25:41 CEST 2013
>> [INFO] Final Memory: 30M/453M
>> [INFO]
>> ------------------------------------------------------------------------
>> *[ERROR] Failed to execute goal
>> org.codehaus.mojo:animal-sniffer-maven-plugin:1.6:check
>> (check-java-1.5-compat) on project async-http-client:
>> Signature errors found. Verify them and put
>> @IgnoreJRERequirement on them. -> [Help 1]*
>> [ERROR]
>> [ERROR] To see the full stack trace of the errors, re-run
>> Maven with the -e switch.
>> [ERROR] Re-run Maven using the -X switch to enable full
>> debug logging.
>> [ERROR]
>> [ERROR] For more information about the errors and
>> possible solutions, please read the following articles:
>> [ERROR] [Help 1]
>> http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
>>
>>
>>
>> 2013/9/10 Sébastien Lorber <lorber.sebastien_at_gmail.com
>> <mailto:lorber.sebastien_at_gmail.com>>
>>
>> Ok thank you, I'll try to implement that today and
>> will give you my feedback :)
>>
>>
>> 2013/9/10 Ryan Lubke <ryan.lubke_at_oracle.com
>> <mailto:ryan.lubke_at_oracle.com>>
>>
>> Okay,
>>
>> I've committed my initial changes to the AHC
>> repository. Here's a summary of the changes:
>>
>>
>> *Improvements to the FeedableBodyGenerator
>> (Grizzly's).
>> - Don't allow queueing of data before
>> initiateAsyncTransfer has been invoked. In low memory
>> heaps, this could lead to an OOM if the source is
>> feeding too fast. The new behavior is to
>> block until initiateAsyncTransfer is called, at
>> which time the blocked thread may proceed with
>> the feed operation.
>> - Introduce the concept of a Feeder.
>> Implementations are responsible, at a high level,
>> for:
>> + letting the provider know that data is
>> available to be fed without blocking
>> + allowing the registration of a callback that
>> the Feeder implementation may invoke
>> to signal that more data is available, if it
>> wasn't available at a previous point in time.
>> - When using a Feeder with a secure request, the
>> SSL handshake will be kicked off by the
>> initiateAsyncTransfer call, but feeding of data
>> will not occur until the handshake is complete.
>> This is necessary as the SSLFilter will queue up
>> all writes until the handshake is complete,
>> and currently, the buffer isn't tied in with the
>> transport flow control mechanism.
>> NOTE: This new SSL behavior is not currently
>> applied when invoking the feed() method
>> outside the context of a Feeder. Still need to
>> address that.
>> - Exposed configuration of the async write queue
>> limit through the FeedableBodyGenerator.
>> This is an improvement on using a
>> TransportCustomizer as any configuration there is
>> transport-wide, and therefor applied to all
>> Connections. By exposing it here, each feeder
>> may have a different byte limit.
>> - Improved documentation for this class*
>>
>>
>>
>> I recommend reading through the javadoc comments
>> in the source [1] for FeedableBodyGenerator
>> (comments welcome).
>> Additionally, I would re-work your code to
>> leverage the Feeder instead of calling feed()
>> directly.
>>
>> If you have issues implementing Feeder, do let us
>> know.
>>
>> If you have additional questions, again, let us know.
>>
>> Thanks,
>> -rl
>>
>> [1]
>> https://github.com/AsyncHttpClient/async-http-client/blob/ahc-1.7.x/src/main/java/com/ning/http/client/providers/grizzly/FeedableBodyGenerator.java
>>
>>
>>
>> Ryan Lubke wrote:
>>>
>>>
>>> Sébastien Lorber wrote:
>>>> So in the end I've end up with an
>>>> implementation that's working for me.
>>>>
>>>>
>>>> I think there are 2 bugs:
>>>>
>>>> 1) The bytes can accumulate in the
>>>> FeedableBodyGenerator queue if the
>>>> initialize(ctx) method is not called fast enough.
>>>> This can be solved by using a BlockingQueue of
>>>> size 1 and the put() method.
>>>>
>>>> 2) Once the context is injected, the
>>>> FeedableBodyGenerator flushes the queue.
>>>> The matter is that if the connection is new,
>>>> not warmed up by a previous request, then the
>>>> SSL handshake is not done yet, and it seems
>>>> that the bytes are accumulated in some part of
>>>> the SSL filter which doesn't deliver them to
>>>> the connection until the handshake has
>>>> completed, so c.canWrite() continues to return
>>>> true.
>>>>
>>>>
>>>>
>>>>
>>>> I have replaced some part of the
>>>> FeedableBodyGenerator to test this and it works
>>>> pretty fine. See what I have changed:
>>>>
>>>> 1)
>>>> private final BlockingQueue<BodyPart> queue
>>>> = new LinkedBlockingQueue<BodyPart>(1);
>>>>
>>>>
>>>> 2)
>>>> public void feed(final Buffer buffer, final
>>>> boolean last) throws IOException {
>>>> try {
>>>> queue.put(new BodyPart(buffer, last));
>>>> } catch (InterruptedException e) {
>>>> throw new RuntimeException(e);
>>>> }
>>>> queueSize.incrementAndGet();
>>>> if (context != null) {
>>>>
>>>> blockUntilConnectionIsReadyToWrite(context);
>>>> flushQueue(true);
>>>> }
>>>> }
>>>>
>>>> private void
>>>> blockUntilConnectionIsReadyToWrite(FilterChainContext
>>>> fcc) {
>>>> if ( !connectionIsReadyToWrite(fcc) ) {
>>>> while ( !connectionIsReadyToWrite(fcc) ) {
>>>> try { Thread.sleep(10); } catch (
>>>> Exception e ) { throw new RuntimeException(e); }
>>>> }
>>>> }
>>>> }
>>>>
>>>> private boolean
>>>> connectionIsReadyToWrite(FilterChainContext fcc) {
>>>> Connection connection =
>>>> fcc.getConnection();
>>>> SSLEngine sslEngine =
>>>> SSLUtils.getSSLEngine(connection);
>>>> return sslEngine != null &&
>>>> !SSLUtils.isHandshaking(sslEngine);
>>>> }
>>>>
>>>>
>>>>
>>>> What do you think?
>>>
>>> We had come to similar conclusions on this end.
>>> I'm still working through testing the idea I
>>> mentioned previously (took longer than I
>>> expected - sorry).
>>> I hope to have something for you to test very soon.
>>>
>>> Note that it will be taking the above into
>>> account as well.
>>>>
>>>>
>>>>
>>>>
>>>> 2013/9/5 Sébastien Lorber
>>>> <lorber.sebastien_at_gmail.com
>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>
>>>>
>>>> I have tried to put a while ( context ==
>>>> null ) Thread.sleep but it doesn't seem to
>>>> work, when the context gets injected, after
>>>> the sleeps, there's an OOM
>>>>
>>>> So I hope you'll have more success with
>>>> your alternative :)
>>>>
>>>>
>>>>
>>>> I have done another test, remember my code
>>>> that worked, which previously "warmed" the
>>>> Thread with an useless request.
>>>>
>>>> private Runnable
>>>> uploadSingleDocumentRunnable = new Runnable() {
>>>> @Override
>>>> public void run() {
>>>> try {
>>>> getUselessSessionCode();
>>>> Thread.sleep(X);
>>>> uploadSingleDocument();
>>>> } catch ( Exception e ) {
>>>> throw new RuntimeException("file
>>>> upload failed",e);
>>>> }
>>>> }
>>>> };
>>>>
>>>> I have put a sleep of X between the useless
>>>> warmup request, and the real upload request
>>>>
>>>>
>>>> What I noticed is that there is a very
>>>> different behavior according to the value of X
>>>>
>>>>
>>>> Under 10 seconds, it seems the stuff is
>>>> still warm, I can upload the documents.
>>>> Around 10 seconds I get a stack which seems
>>>> to be "connection closed" or something
>>>> Above 10 seconds, I get OOM like if the
>>>> stuff wasn't warm.
>>>>
>>>>
>>>> The stacks I get for 10 seconds looks like
>>>>
>>>> Caused by: javax.net.ssl.SSLException:
>>>> SSLEngine is CLOSED
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrap(SSLConnectionContext.java:295)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrapAll(SSLConnectionContext.java:238)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.wrapAll(SSLBaseFilter.java:405)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.handleWrite(SSLBaseFilter.java:320)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLFilter.accurateWrite(SSLFilter.java:255)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ssl.SSLFilter.handleWrite(SSLFilter.java:143)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider$SwitchingSSLFilter.handleWrite(GrizzlyAsyncHttpProvider.java:2500)
>>>> ~[async-http-client-1.7.20-SNAPSHOT.jar:na]
>>>> at
>>>> org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:111)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:853)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:720)
>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>> at
>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.flushQueue(FeedableBodyGenerator.java:133)
>>>> ~[async-http-client-1.7.20-SNAPSHOT.jar:na]
>>>> at
>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.feed(FeedableBodyGenerator.java:95)
>>>> ~[async-http-client-1.7.20-SNAPSHOT.jar:na]
>>>>
>>>> I think I got some other different stacks
>>>> saying Connection Closed Remotely or
>>>> something like that.
>>>>
>>>>
>>>>
>>>>
>>>> So it seems that something is bound to my
>>>> thread, and it stays bound to it for about
>>>> 10 seconds, do you have any idea what it
>>>> could be?
>>>> (My connection timeout setting seems to
>>>> have no effect on this 10s threshold)
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> 2013/9/5 Ryan Lubke <ryan.lubke_at_oracle.com
>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>
>>>> That is one solution. I'm working out
>>>> an alternative right now. Stay tuned!
>>>>
>>>>>
>>>>> Anyway it's not a problem, I think the
>>>>> FeedableBodyGenerator.feed() method
>>>>> just has to block until a context has
>>>>> been (and ThreadCache initialized) to
>>>>> avoid OOM errors
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2013/9/5 Sébastien Lorber
>>>>> <lorber.sebastien_at_gmail.com
>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>
>>>>>
>>>>> What is very strange is that I
>>>>> tested with/without the same
>>>>> sessionCode with our previous
>>>>> code, the one not using
>>>>> FeedableBodyGenerator, which has a
>>>>> high memory consumption.
>>>>> Despites the fact it had high
>>>>> memory consumption, it seems work
>>>>> fine to upload multiple documents
>>>>> if allocated with a large heap,
>>>>> and the sessionCode seems to have
>>>>> no effect.
>>>>>
>>>>> On the new impl using the
>>>>> FeedableBodyGenerator, the
>>>>> sessionCode sent as a multipart
>>>>> bodypart seems to have an effect.
>>>>>
>>>>> I have tried to feed the queue
>>>>> before sending the request to AHC,
>>>>> but this leads to this exception
>>>>> (with/without sessionCode switching)
>>>>> Caused by:
>>>>> java.util.concurrent.TimeoutException:
>>>>> Timeout exceeded
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider.timeout(GrizzlyAsyncHttpProvider.java:528)
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider$3.onTimeout(GrizzlyAsyncHttpProvider.java:361)
>>>>> at
>>>>> org.glassfish.grizzly.utils.IdleTimeoutFilter$DefaultWorker.doWork(IdleTimeoutFilter.java:383)
>>>>> at
>>>>> org.glassfish.grizzly.utils.IdleTimeoutFilter$DefaultWorker.doWork(IdleTimeoutFilter.java:362)
>>>>> at
>>>>> org.glassfish.grizzly.utils.DelayedExecutor$DelayedRunnable.run(DelayedExecutor.java:158)
>>>>> at
>>>>> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
>>>>> at
>>>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2013/9/5 Sébastien Lorber
>>>>> <lorber.sebastien_at_gmail.com
>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>
>>>>> By the way, by using a low
>>>>> timeout with the same
>>>>> sessioncode, I got the
>>>>> following NPE:
>>>>>
>>>>> Caused by:
>>>>> java.lang.NullPointerException
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.block(FeedableBodyGenerator.java:184)
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.blockUntilQueueFree(FeedableBodyGenerator.java:167)
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.flushQueue(FeedableBodyGenerator.java:124)
>>>>> at
>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.feed(FeedableBodyGenerator.java:94)
>>>>>
>>>>>
>>>>> GrizzlyAsyncHttpProvider.HttpTransactionContext
>>>>> httpCtx =
>>>>>
>>>>> getHttpTransactionContext(c);
>>>>>
>>>>> httpCtx.abort(e.getCause());
>>>>>
>>>>> I guess the httpCtx is not
>>>>> already available to be aborted
>>>>>
>>>>>
>>>>> 2013/9/5 Sébastien Lorber
>>>>> <lorber.sebastien_at_gmail.com
>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>
>>>>>
>>>>>
>>>>> This is right, here's a
>>>>> log I have when I use the
>>>>> same session code, ie the
>>>>> remote host is blocking
>>>>> the data or something.
>>>>> This is obtained by
>>>>> running 5 parallel uploads.
>>>>>
>>>>> *Flushing queue of size 0
>>>>> with allowBlocking = false*
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> *Flushing queue of size 97
>>>>> with allowBlocking = false*
>>>>> *Flushing queue of size
>>>>> 100 with allowBlocking =
>>>>> false*
>>>>> *Flushing queue of size
>>>>> 160 with allowBlocking = true*
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 0
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> java.lang.OutOfMemoryError: GC
>>>>> overhead limit exceeded
>>>>> Dumping heap to
>>>>> /ome/lorber/ureau/om ...
>>>>> Unable to create
>>>>> /ome/lorber/ureau/om: Le
>>>>> fichier existe
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Disconnected from the
>>>>> target VM, address:
>>>>> '127.0.0.1:49268
>>>>> <http://127.0.0.1:49268>',
>>>>> transport: 'socket'
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Otherwise, with different
>>>>> session codes, I get the
>>>>> following:
>>>>>
>>>>> *Flushing queue of size 0
>>>>> with allowBlocking = false*
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> *Flushing queue of size 0
>>>>> with allowBlocking = false*
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> *Flushing queue of size 0
>>>>> with allowBlocking = false*
>>>>> *Flushing queue of size 0
>>>>> with allowBlocking = false*
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> Flushing queue of size 1
>>>>> with allowBlocking = true
>>>>> ... and this continues
>>>>> without OOM
>>>>>
>>>>>
>>>>> So, this seems to be the
>>>>> problem.
>>>>>
>>>>>
>>>>>
>>>>> I think it would be great
>>>>> to be able to be able to
>>>>> choose the queue impl
>>>>> behind
>>>>> that FeedableBodyGenerator, like
>>>>> I suggested in my pull
>>>>> request.
>>>>>
>>>>> See here:
>>>>> https://github.com/slorber/async-http-client/blob/79b0c3b28a61b0aa4c4b055bca8f6be11d9ed1e6/src/main/java/com/ning/http/client/providers/grizzly/FeedableBodyGenerator.java
>>>>>
>>>>> Using a
>>>>> LinkedBlockingQueue seems
>>>>> to be a nice idea in this
>>>>> context, and in my case I
>>>>> would probably use a queue
>>>>> of size 1
>>>>>
>>>>>
>>>>> This would handle the
>>>>> blocking of the feed
>>>>> method, without having to
>>>>> use this:
>>>>> if (context != null) {
>>>>> flushQueue(true);
>>>>> }
>>>>>
>>>>>
>>>>> Or perhaps the feed()
>>>>> method have to wait until
>>>>> a context is set in the
>>>>> BodyGenerator ?
>>>>>
>>>>>
>>>>> I think it would be more
>>>>> clear if
>>>>> the initializeAsynchronousTransfer
>>>>> simply didn't flush the
>>>>> queue but just setup the
>>>>> context.
>>>>> Then the feed method would
>>>>> block until there's a
>>>>> context set, and then
>>>>> flush the queue with
>>>>> blocking behavior.
>>>>>
>>>>> This is probably the next
>>>>> step, but as we are using
>>>>> AHC for async, it would
>>>>> probably be great if that
>>>>> blocking feed() method was
>>>>> called in a worker thread
>>>>> instead of our main thread.
>>>>> I won't use this but
>>>>> someone who really wants a
>>>>> non-blocking impl of
>>>>> performant multipart
>>>>> fileupload would probably
>>>>> need this, or will use an
>>>>> ExecutorService for the
>>>>> feeding operations as a
>>>>> workaround.
>>>>>
>>>>>
>>>>>
>>>>> Thanks again for your
>>>>> reactivity
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2013/9/4 Ryan Lubke
>>>>> <ryan.lubke_at_oracle.com
>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>
>>>>>
>>>>>
>>>>> Sébastien Lorber wrote:
>>>>>> I've integrated this
>>>>>> change and it works
>>>>>> fine except a little
>>>>>> detail.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I'm uploading files
>>>>>> to a third party API
>>>>>> (a bit like S3).
>>>>>> This API requires a
>>>>>> "sessionCode" in each
>>>>>> request. So there is
>>>>>> a multipart
>>>>>> StringPart with that
>>>>>> SessionCode.
>>>>>>
>>>>>> We used to have a
>>>>>> cache which holds the
>>>>>> sessionCode 30min per
>>>>>> user so that we do
>>>>>> not need to init a
>>>>>> new session each time.
>>>>>>
>>>>>> I had troubles in
>>>>>> this very specific
>>>>>> case: when I upload 5
>>>>>> docs with the same
>>>>>> session code.
>>>>>> When I remove the
>>>>>> cache and use 5
>>>>>> different session
>>>>>> codes, it works fine.
>>>>>>
>>>>>> I guess the remote
>>>>>> service is blocking
>>>>>> concurrent uploads
>>>>>> with the same session
>>>>>> code. I don't know at
>>>>>> all.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Where I want to go is
>>>>>> that I wouldn't have
>>>>>> expected Grizzly to OOM
>>>>>>
>>>>>>
>>>>>> Avertissement:
>>>>>> Exception during
>>>>>> FilterChain execution
>>>>>> java.lang.OutOfMemoryError:
>>>>>> Java heap space
>>>>>> at
>>>>>> java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57)
>>>>>> at
>>>>>> java.nio.ByteBuffer.allocate(ByteBuffer.java:331)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLUtils.allocateOutputBuffer(SSLUtils.java:342)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter$2.grow(SSLBaseFilter.java:117)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.ensureBufferSize(SSLConnectionContext.java:392)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrap(SSLConnectionContext.java:272)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrapAll(SSLConnectionContext.java:238)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.wrapAll(SSLBaseFilter.java:405)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.handleWrite(SSLBaseFilter.java:320)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLFilter.accurateWrite(SSLFilter.java:263)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLFilter.handleWrite(SSLFilter.java:143)
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider$SwitchingSSLFilter.handleWrite(GrizzlyAsyncHttpProvider.java:2500)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:111)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
>>>>>> at
>>>>>> org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.FilterChainContext$1.run(FilterChainContext.java:196)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.FilterChainContext.resume(FilterChainContext.java:220)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLFilter$SSLHandshakeContext.completed(SSLFilter.java:383)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLFilter.notifyHandshakeComplete(SSLFilter.java:278)
>>>>>> at
>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.handleRead(SSLBaseFilter.java:275)
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider$SwitchingSSLFilter.handleRead(GrizzlyAsyncHttpProvider.java:2490)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
>>>>>> at
>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
>>>>>> at
>>>>>> org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
>>>>>> at
>>>>>> org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:546)
>>>>>> at
>>>>>> org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Caused by:
>>>>>> java.util.concurrent.TimeoutException:
>>>>>> null
>>>>>> at
>>>>>> org.glassfish.grizzly.impl.SafeFutureImpl$Sync.innerGet(SafeFutureImpl.java:367)
>>>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>>>> at
>>>>>> org.glassfish.grizzly.impl.SafeFutureImpl.get(SafeFutureImpl.java:274)
>>>>>> ~[grizzly-framework-2.3.5.jar:2.3.5]
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.block(FeedableBodyGenerator.java:177)
>>>>>> ~[async-http-client-1.7.20-204092c.jar:na]
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.blockUntilQueueFree(FeedableBodyGenerator.java:167)
>>>>>> ~[async-http-client-1.7.20-204092c.jar:na]
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.flushQueue(FeedableBodyGenerator.java:124)
>>>>>> ~[async-http-client-1.7.20-204092c.jar:na]
>>>>>> at
>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.feed(FeedableBodyGenerator.java:94)
>>>>>> ~[async-http-client-1.7.20-204092c.jar:na]
>>>>>>
>>>>>>
>>>>>>
>>>>>> multipart.body.generator.feeder.buffer=100000
>>>>>> -> size of each
>>>>>> Buffer sent to the
>>>>>> FeedableBodyGenerator
>>>>>> transport.max.pending.bytes=1000000
>>>>>> (I tried other
>>>>>> settings, including
>>>>>> AUTO_SIZE)
>>>>>>
>>>>>>
>>>>>>
>>>>>> Do you have any idea
>>>>>> why is there an OOM
>>>>>> with these settings?
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Perhaps it is because
>>>>>> the feed() method of
>>>>>> FeedableBodyGenerator
>>>>>> doesn't block until
>>>>>> the context is
>>>>>> initialized.
>>>>>> I guess
>>>>>> the initializeAsynchronousTransfer
>>>>>> is called only once
>>>>>> the connection is
>>>>>> established, and
>>>>>> perhaps a lot of
>>>>>> Buffer are added to
>>>>>> the queue...
>>>>> Yes, it's invoked once
>>>>> the request has been
>>>>> dispatched, so if the
>>>>> generator is fed a lot
>>>>> before the request, I
>>>>> could see this happening.
>>>>> I'll see what I can do
>>>>> to alleviate that case.
>>>>>
>>>>>>
>>>>>> But I'm not sure at
>>>>>> all because the
>>>>>> session code is
>>>>>> transmitted as a
>>>>>> BodyPart and I get
>>>>>> the same problem if i
>>>>>> put it as the first
>>>>>> or last multipart.
>>>>>>
>>>>>> It's not a big deal,
>>>>>> perhaps I should
>>>>>> always use a
>>>>>> different session
>>>>>> code for concurrent
>>>>>> operations but I'd
>>>>>> like to be sure that
>>>>>> we won't have this
>>>>>> issue in production...
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> 2013/9/3 Ryan Lubke
>>>>>> <ryan.lubke_at_oracle.com <mailto:ryan.lubke_at_oracle.com>>
>>>>>>
>>>>>> Good catch. Fixed.
>>>>>>
>>>>>>
>>>>>> Sébastien Lorber
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>>
>>>>>>> There's a little
>>>>>>> mistake in the
>>>>>>> grizzly ahc
>>>>>>> provider
>>>>>>> relative to the
>>>>>>> write queue size.
>>>>>>>
>>>>>>>
>>>>>>> https://github.com/AsyncHttpClient/async-http-client/blob/b5d97efe9fe14113ea92fb1f7db192a2d090fad7/src/main/java/com/ning/http/client/providers/grizzly/GrizzlyAsyncHttpProvider.java#L419
>>>>>>>
>>>>>>> As you can see,
>>>>>>> the
>>>>>>> TransportCustomizer
>>>>>>> is called, and
>>>>>>> then the write
>>>>>>> queue size
>>>>>>> (among other
>>>>>>> things) is set
>>>>>>> to AUTO_SIZE
>>>>>>> (instead of
>>>>>>> previously
>>>>>>> UNLIMITED)
>>>>>>>
>>>>>>> clientTransport.getAsyncQueueIO().getWriter()
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> .setMaxPendingBytesPerConnection(AsyncQueueWriter.AUTO_SIZE);
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I think the
>>>>>>> default settings
>>>>>>> like this
>>>>>>> AUTO_SIZE
>>>>>>> attribute should
>>>>>>> be set before
>>>>>>> the
>>>>>>> customization of
>>>>>>> the transport,
>>>>>>> or they would
>>>>>>> override the
>>>>>>> value we customized.
>>>>>>>
>>>>>>>
>>>>>>> This is actually
>>>>>>> my case, since I
>>>>>>> can't reproduce
>>>>>>> my "bug" which
>>>>>>> is "high memory
>>>>>>> consumption",
>>>>>>> even when using
>>>>>>> -1 / UNLIMITED
>>>>>>> in the
>>>>>>> TransportCustomizer.
>>>>>>>
>>>>>>>
>>>>>>> This could work
>>>>>>> fine for me with
>>>>>>> AUTO_SIZE, but
>>>>>>> I'd rather be
>>>>>>> able to tune
>>>>>>> this parameter
>>>>>>> during load
>>>>>>> tests to see the
>>>>>>> effect.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> 2013/8/31
>>>>>>> Sebastien Lorber
>>>>>>> <lorber.sebastien_at_gmail.com
>>>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>>>
>>>>>>> Thanks i
>>>>>>> will ckeck
>>>>>>> that on
>>>>>>> monday. I
>>>>>>> can now
>>>>>>> upload a
>>>>>>> 500m file
>>>>>>> with 40m
>>>>>>> heap size ;)
>>>>>>>
>>>>>>> Envoyé de
>>>>>>> mon iPhone
>>>>>>>
>>>>>>> Le 30 août
>>>>>>> 2013 à
>>>>>>> 20:49, Ryan
>>>>>>> Lubke
>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>> a écrit :
>>>>>>>
>>>>>>>> I'm going
>>>>>>>> to be
>>>>>>>> updating
>>>>>>>> the Grizzly
>>>>>>>> provider
>>>>>>>> such that
>>>>>>>> AUTO_SIZE
>>>>>>>> (not
>>>>>>>> AUTO_TUNE)
>>>>>>>> is the
>>>>>>>> default, so
>>>>>>>> you can
>>>>>>>> avoid the
>>>>>>>> use of the
>>>>>>>> TransportCustomizer.
>>>>>>>>
>>>>>>>> Ryan Lubke
>>>>>>>> wrote:
>>>>>>>>> Regarding
>>>>>>>>> your
>>>>>>>>> tuning
>>>>>>>>> question,
>>>>>>>>> I would
>>>>>>>>> probably
>>>>>>>>> set the
>>>>>>>>> value to
>>>>>>>>> AsyncQueueWriter.AUTO_TUNE
>>>>>>>>> (this will
>>>>>>>>> be four
>>>>>>>>> times the
>>>>>>>>> socket
>>>>>>>>> write
>>>>>>>>> buffer)
>>>>>>>>> and see
>>>>>>>>> how that
>>>>>>>>> works.
>>>>>>>>>
>>>>>>>>> Ryan Lubke
>>>>>>>>> wrote:
>>>>>>>>>> A
>>>>>>>>>> question
>>>>>>>>>> first.
>>>>>>>>>> With
>>>>>>>>>> these
>>>>>>>>>> changes,
>>>>>>>>>> your
>>>>>>>>>> memory
>>>>>>>>>> usage is
>>>>>>>>>> more
>>>>>>>>>> inline
>>>>>>>>>> with what
>>>>>>>>>> you were
>>>>>>>>>> looking for?
>>>>>>>>>>
>>>>>>>>>> Sébastien
>>>>>>>>>> Lorber
>>>>>>>>>> wrote:
>>>>>>>>>>> By the
>>>>>>>>>>> way, do
>>>>>>>>>>> you have
>>>>>>>>>>> any idea
>>>>>>>>>>> when the
>>>>>>>>>>> 1.7.20
>>>>>>>>>>> will be
>>>>>>>>>>> released
>>>>>>>>>>> (with
>>>>>>>>>>> these
>>>>>>>>>>> new
>>>>>>>>>>> improvements?)
>>>>>>>>>>>
>>>>>>>>>>> We would
>>>>>>>>>>> like to
>>>>>>>>>>> know if
>>>>>>>>>>> we wait
>>>>>>>>>>> for a
>>>>>>>>>>> release
>>>>>>>>>>> or if we
>>>>>>>>>>> install
>>>>>>>>>>> our own
>>>>>>>>>>> temp
>>>>>>>>>>> release
>>>>>>>>>>> on Nexus :)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 2013/8/30 Sébastien
>>>>>>>>>>> Lorber
>>>>>>>>>>> <lorber.sebastien_at_gmail.com
>>>>>>>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>>>>>>>
>>>>>>>>>>> Thank you,
>>>>>>>>>>> it
>>>>>>>>>>> works fine!
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I
>>>>>>>>>>> just
>>>>>>>>>>> had
>>>>>>>>>>> to
>>>>>>>>>>> modify
>>>>>>>>>>> a
>>>>>>>>>>> single
>>>>>>>>>>> line
>>>>>>>>>>> after your
>>>>>>>>>>> commit.
>>>>>>>>>>>
>>>>>>>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider#initializeTransport
>>>>>>>>>>> ->
>>>>>>>>>>> clientTransport.getAsyncQueueIO().getWriter().setMaxPendingBytesPerConnection(10000);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> If I
>>>>>>>>>>> let
>>>>>>>>>>> the
>>>>>>>>>>> initial
>>>>>>>>>>> value (-1)
>>>>>>>>>>> it
>>>>>>>>>>> won't block,
>>>>>>>>>>> canWrite
>>>>>>>>>>> always
>>>>>>>>>>> returns
>>>>>>>>>>> true
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Btw,
>>>>>>>>>>> on
>>>>>>>>>>> AHC
>>>>>>>>>>> I
>>>>>>>>>>> didn't
>>>>>>>>>>> find
>>>>>>>>>>> any
>>>>>>>>>>> way
>>>>>>>>>>> to
>>>>>>>>>>> pass
>>>>>>>>>>> this
>>>>>>>>>>> value as
>>>>>>>>>>> a
>>>>>>>>>>> config
>>>>>>>>>>> attribute,
>>>>>>>>>>> neither
>>>>>>>>>>> the
>>>>>>>>>>> size
>>>>>>>>>>> of
>>>>>>>>>>> the
>>>>>>>>>>> write buffer
>>>>>>>>>>> you
>>>>>>>>>>> talked
>>>>>>>>>>> about.
>>>>>>>>>>>
>>>>>>>>>>> So
>>>>>>>>>>> in
>>>>>>>>>>> the
>>>>>>>>>>> end,
>>>>>>>>>>> is
>>>>>>>>>>> there a
>>>>>>>>>>> way
>>>>>>>>>>> with
>>>>>>>>>>> current
>>>>>>>>>>> AHC
>>>>>>>>>>> code
>>>>>>>>>>> to
>>>>>>>>>>> use
>>>>>>>>>>> this
>>>>>>>>>>> "canWrite
>>>>>>>>>>> =
>>>>>>>>>>> false"
>>>>>>>>>>> behavior?
>>>>>>>>>>>
>>>>>>>>>>> If
>>>>>>>>>>> not,
>>>>>>>>>>> can
>>>>>>>>>>> you
>>>>>>>>>>> please
>>>>>>>>>>> provide
>>>>>>>>>>> a
>>>>>>>>>>> way
>>>>>>>>>>> to
>>>>>>>>>>> set
>>>>>>>>>>> this
>>>>>>>>>>> behavior
>>>>>>>>>>> on
>>>>>>>>>>> v1.7.20
>>>>>>>>>>> ? thanks
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> PS:
>>>>>>>>>>> does
>>>>>>>>>>> it
>>>>>>>>>>> make
>>>>>>>>>>> sens
>>>>>>>>>>> to
>>>>>>>>>>> use
>>>>>>>>>>> the
>>>>>>>>>>> same
>>>>>>>>>>> number
>>>>>>>>>>> of
>>>>>>>>>>> bytes un
>>>>>>>>>>> the
>>>>>>>>>>> feed(Buffer)
>>>>>>>>>>> method
>>>>>>>>>>> and
>>>>>>>>>>> in
>>>>>>>>>>> the
>>>>>>>>>>> setMaxPendingBytesPerConnection(10000);
>>>>>>>>>>> ? do
>>>>>>>>>>> you
>>>>>>>>>>> have
>>>>>>>>>>> any
>>>>>>>>>>> tuning
>>>>>>>>>>> recommandation?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 2013/8/29
>>>>>>>>>>> Ryan
>>>>>>>>>>> Lubke <ryan.lubke_at_oracle.com
>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>
>>>>>>>>>>> Please
>>>>>>>>>>> disregard.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Ryan
>>>>>>>>>>> Lubke
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Sébastien,
>>>>>>>>>>>>
>>>>>>>>>>>> Could
>>>>>>>>>>>> you
>>>>>>>>>>>> also
>>>>>>>>>>>> provide
>>>>>>>>>>>> a
>>>>>>>>>>>> sample
>>>>>>>>>>>> of
>>>>>>>>>>>> how
>>>>>>>>>>>> you're
>>>>>>>>>>>> performing
>>>>>>>>>>>> your
>>>>>>>>>>>> feed?
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>> -rl
>>>>>>>>>>>>
>>>>>>>>>>>> Ryan
>>>>>>>>>>>> Lubke
>>>>>>>>>>>> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Sébastien,
>>>>>>>>>>>>>
>>>>>>>>>>>>> I'd
>>>>>>>>>>>>> recommend
>>>>>>>>>>>>> looking
>>>>>>>>>>>>> at
>>>>>>>>>>>>> Connection.canWrite()
>>>>>>>>>>>>> [1]
>>>>>>>>>>>>> and
>>>>>>>>>>>>> Connection.notifyCanWrite(WriteListener)
>>>>>>>>>>>>> [1]
>>>>>>>>>>>>>
>>>>>>>>>>>>> By
>>>>>>>>>>>>> default,
>>>>>>>>>>>>> Grizzly
>>>>>>>>>>>>> will
>>>>>>>>>>>>> configure
>>>>>>>>>>>>> the
>>>>>>>>>>>>> async
>>>>>>>>>>>>> write
>>>>>>>>>>>>> queue
>>>>>>>>>>>>> length
>>>>>>>>>>>>> to
>>>>>>>>>>>>> be
>>>>>>>>>>>>> four
>>>>>>>>>>>>> times
>>>>>>>>>>>>> the
>>>>>>>>>>>>> write
>>>>>>>>>>>>> buffer
>>>>>>>>>>>>> size
>>>>>>>>>>>>> (which
>>>>>>>>>>>>> is
>>>>>>>>>>>>> based
>>>>>>>>>>>>> off
>>>>>>>>>>>>> the
>>>>>>>>>>>>> socket
>>>>>>>>>>>>> write
>>>>>>>>>>>>> buffer).
>>>>>>>>>>>>> When
>>>>>>>>>>>>> this
>>>>>>>>>>>>> queue
>>>>>>>>>>>>> exceeds
>>>>>>>>>>>>> this
>>>>>>>>>>>>> value,
>>>>>>>>>>>>> canWrite()
>>>>>>>>>>>>> will
>>>>>>>>>>>>> return
>>>>>>>>>>>>> false.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> When
>>>>>>>>>>>>> this
>>>>>>>>>>>>> occurs,
>>>>>>>>>>>>> you
>>>>>>>>>>>>> can
>>>>>>>>>>>>> register
>>>>>>>>>>>>> a WriteListener
>>>>>>>>>>>>> to
>>>>>>>>>>>>> be
>>>>>>>>>>>>> notified
>>>>>>>>>>>>> when
>>>>>>>>>>>>> the
>>>>>>>>>>>>> queue
>>>>>>>>>>>>> length
>>>>>>>>>>>>> is
>>>>>>>>>>>>> below
>>>>>>>>>>>>> the
>>>>>>>>>>>>> configured
>>>>>>>>>>>>> max
>>>>>>>>>>>>> and
>>>>>>>>>>>>> then
>>>>>>>>>>>>> simulate
>>>>>>>>>>>>> blocking
>>>>>>>>>>>>> until
>>>>>>>>>>>>> the
>>>>>>>>>>>>> onWritePossible()
>>>>>>>>>>>>> callback
>>>>>>>>>>>>> has
>>>>>>>>>>>>> been
>>>>>>>>>>>>> invoked.
>>>>>>>>>>>>>
>>>>>>>>>>>>> ----------------------------------------------------------------
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> final
>>>>>>>>>>>>> FutureImpl<Boolean>
>>>>>>>>>>>>> future
>>>>>>>>>>>>> = Futures.createSafeFuture();
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> //
>>>>>>>>>>>>> Connection
>>>>>>>>>>>>> may
>>>>>>>>>>>>> be
>>>>>>>>>>>>> obtained
>>>>>>>>>>>>> by
>>>>>>>>>>>>> calling
>>>>>>>>>>>>> FilterChainContext.getConnection().
>>>>>>>>>>>>>
>>>>>>>>>>>>> connection.notifyCanWrite(new
>>>>>>>>>>>>> WriteHandler()
>>>>>>>>>>>>> {
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> @Override
>>>>>>>>>>>>>
>>>>>>>>>>>>> public
>>>>>>>>>>>>> void
>>>>>>>>>>>>> onWritePossible()
>>>>>>>>>>>>> throws
>>>>>>>>>>>>> Exception
>>>>>>>>>>>>> {
>>>>>>>>>>>>>
>>>>>>>>>>>>> future.result(Boolean.TRUE);
>>>>>>>>>>>>>
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> @Override
>>>>>>>>>>>>>
>>>>>>>>>>>>> public
>>>>>>>>>>>>> void
>>>>>>>>>>>>> onError(Throwable
>>>>>>>>>>>>> t)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>
>>>>>>>>>>>>> future.failure(Exceptions.makeIOException(t));
>>>>>>>>>>>>>
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> });
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> try
>>>>>>>>>>>>> {
>>>>>>>>>>>>>
>>>>>>>>>>>>> final
>>>>>>>>>>>>> long
>>>>>>>>>>>>> writeTimeout
>>>>>>>>>>>>> = 30;
>>>>>>>>>>>>>
>>>>>>>>>>>>> future.get(writeTimeout,
>>>>>>>>>>>>> TimeUnit.MILLISECONDS);
>>>>>>>>>>>>>
>>>>>>>>>>>>> } catch
>>>>>>>>>>>>> (ExecutionException
>>>>>>>>>>>>> e)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>
>>>>>>>>>>>>> HttpTransactionContext
>>>>>>>>>>>>> httpCtx
>>>>>>>>>>>>> = HttpTransactionContext.get(connection);
>>>>>>>>>>>>>
>>>>>>>>>>>>> httpCtx.abort(e.getCause());
>>>>>>>>>>>>>
>>>>>>>>>>>>> } catch
>>>>>>>>>>>>> (Exception
>>>>>>>>>>>>> e)
>>>>>>>>>>>>> {
>>>>>>>>>>>>> HttpTransactionContext
>>>>>>>>>>>>> httpCtx
>>>>>>>>>>>>> = HttpTransactionContext.get(connection);
>>>>>>>>>>>>>
>>>>>>>>>>>>> httpCtx.abort(e);
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>>>>>>
>>>>>>>>>>>>> [1]
>>>>>>>>>>>>> http://grizzly.java.net/docs/2.3/apidocs/org/glassfish/grizzly/OutputSink.html.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Ryan,
>>>>>>>>>>>>>> I've
>>>>>>>>>>>>>> did
>>>>>>>>>>>>>> some
>>>>>>>>>>>>>> other
>>>>>>>>>>>>>> tests.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> It
>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>> that
>>>>>>>>>>>>>> using
>>>>>>>>>>>>>> a blocking
>>>>>>>>>>>>>> queue
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> FeedableBodyGenerator
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> totally
>>>>>>>>>>>>>> useless
>>>>>>>>>>>>>> because
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> thread
>>>>>>>>>>>>>> consuming
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> not
>>>>>>>>>>>>>> blocking
>>>>>>>>>>>>>> and
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> queue
>>>>>>>>>>>>>> never
>>>>>>>>>>>>>> blocks
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> feeding,
>>>>>>>>>>>>>> which
>>>>>>>>>>>>>> was
>>>>>>>>>>>>>> my
>>>>>>>>>>>>>> intention
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> beginning.
>>>>>>>>>>>>>> Maybe
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> depends
>>>>>>>>>>>>>> on
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> IO
>>>>>>>>>>>>>> strategy
>>>>>>>>>>>>>> used?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I use
>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>> default
>>>>>>>>>>>>>> which
>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> use SameThreadIOStrategy
>>>>>>>>>>>>>> so
>>>>>>>>>>>>>> I don't
>>>>>>>>>>>>>> think
>>>>>>>>>>>>>> it's
>>>>>>>>>>>>>> related
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> IO
>>>>>>>>>>>>>> strategy.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> So
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> end
>>>>>>>>>>>>>> I can
>>>>>>>>>>>>>> upload
>>>>>>>>>>>>>> a 70m
>>>>>>>>>>>>>> file
>>>>>>>>>>>>>> with
>>>>>>>>>>>>>> a heap
>>>>>>>>>>>>>> of
>>>>>>>>>>>>>> 50m,
>>>>>>>>>>>>>> but
>>>>>>>>>>>>>> I have
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> put
>>>>>>>>>>>>>> a Thread.sleep(30)
>>>>>>>>>>>>>> between
>>>>>>>>>>>>>> each
>>>>>>>>>>>>>> 100k
>>>>>>>>>>>>>> Buffer
>>>>>>>>>>>>>> send
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> FeedableBodyGenerator
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The
>>>>>>>>>>>>>> connection
>>>>>>>>>>>>>> with
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> server
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> not
>>>>>>>>>>>>>> good
>>>>>>>>>>>>>> here,
>>>>>>>>>>>>>> but
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> production
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> normally
>>>>>>>>>>>>>> a lot
>>>>>>>>>>>>>> better
>>>>>>>>>>>>>> as
>>>>>>>>>>>>>> far
>>>>>>>>>>>>>> as
>>>>>>>>>>>>>> I know.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I've
>>>>>>>>>>>>>> tried
>>>>>>>>>>>>>> things
>>>>>>>>>>>>>> like clientTransport.getAsyncQueueIO().getWriter().setMaxPendingBytesPerConnection(100000);
>>>>>>>>>>>>>> but
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> doesn't
>>>>>>>>>>>>>> seem
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> work
>>>>>>>>>>>>>> for
>>>>>>>>>>>>>> me.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'd
>>>>>>>>>>>>>> like
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> Grizzly
>>>>>>>>>>>>>> internals
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> block
>>>>>>>>>>>>>> when
>>>>>>>>>>>>>> there
>>>>>>>>>>>>>> are
>>>>>>>>>>>>>> too
>>>>>>>>>>>>>> much
>>>>>>>>>>>>>> pending
>>>>>>>>>>>>>> bytes
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> send.
>>>>>>>>>>>>>> Is
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> possible?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> PS:
>>>>>>>>>>>>>> I've
>>>>>>>>>>>>>> just
>>>>>>>>>>>>>> been
>>>>>>>>>>>>>> able
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> send
>>>>>>>>>>>>>> a 500mo
>>>>>>>>>>>>>> file
>>>>>>>>>>>>>> with
>>>>>>>>>>>>>> 100mo
>>>>>>>>>>>>>> heap,
>>>>>>>>>>>>>> but
>>>>>>>>>>>>>> it
>>>>>>>>>>>>>> needed
>>>>>>>>>>>>>> a sleep
>>>>>>>>>>>>>> of
>>>>>>>>>>>>>> 100ms
>>>>>>>>>>>>>> between
>>>>>>>>>>>>>> each
>>>>>>>>>>>>>> 100k
>>>>>>>>>>>>>> Buffer
>>>>>>>>>>>>>> sent
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> bodygenerator
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2013/8/29
>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>> <lorber.sebastien_at_gmail.com
>>>>>>>>>>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> By
>>>>>>>>>>>>>> chance
>>>>>>>>>>>>>> do
>>>>>>>>>>>>>> you
>>>>>>>>>>>>>> if
>>>>>>>>>>>>>> I can
>>>>>>>>>>>>>> remove
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> MessageCloner
>>>>>>>>>>>>>> used
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> SSL
>>>>>>>>>>>>>> filter?
>>>>>>>>>>>>>> SSLBaseFilter$OnWriteCopyCloner
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> It
>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> allocate
>>>>>>>>>>>>>> a lot
>>>>>>>>>>>>>> of
>>>>>>>>>>>>>> memory.
>>>>>>>>>>>>>> I don't
>>>>>>>>>>>>>> really
>>>>>>>>>>>>>> understand
>>>>>>>>>>>>>> why
>>>>>>>>>>>>>> messages
>>>>>>>>>>>>>> have
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> be
>>>>>>>>>>>>>> cloned,
>>>>>>>>>>>>>> can
>>>>>>>>>>>>>> I remove
>>>>>>>>>>>>>> this?
>>>>>>>>>>>>>> How?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2013/8/29
>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>> <lorber.sebastien_at_gmail.com
>>>>>>>>>>>>>> <mailto:lorber.sebastien_at_gmail.com>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'm
>>>>>>>>>>>>>> trying
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> send
>>>>>>>>>>>>>> a 500m
>>>>>>>>>>>>>> file
>>>>>>>>>>>>>> for
>>>>>>>>>>>>>> my
>>>>>>>>>>>>>> tests
>>>>>>>>>>>>>> with
>>>>>>>>>>>>>> a heap
>>>>>>>>>>>>>> of
>>>>>>>>>>>>>> 400m.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> In
>>>>>>>>>>>>>> our
>>>>>>>>>>>>>> real
>>>>>>>>>>>>>> use
>>>>>>>>>>>>>> cases
>>>>>>>>>>>>>> we
>>>>>>>>>>>>>> would
>>>>>>>>>>>>>> probably
>>>>>>>>>>>>>> have
>>>>>>>>>>>>>> files
>>>>>>>>>>>>>> under
>>>>>>>>>>>>>> 20mo
>>>>>>>>>>>>>> but
>>>>>>>>>>>>>> we
>>>>>>>>>>>>>> want
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> reduce
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> memory
>>>>>>>>>>>>>> consumption
>>>>>>>>>>>>>> because
>>>>>>>>>>>>>> we
>>>>>>>>>>>>>> can
>>>>>>>>>>>>>> have
>>>>>>>>>>>>>> x parallel
>>>>>>>>>>>>>> uploads
>>>>>>>>>>>>>> on
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> same
>>>>>>>>>>>>>> server
>>>>>>>>>>>>>> according
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> user
>>>>>>>>>>>>>> activity.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>> try
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> check
>>>>>>>>>>>>>> if
>>>>>>>>>>>>>> using
>>>>>>>>>>>>>> this
>>>>>>>>>>>>>> BodyGenerator
>>>>>>>>>>>>>> reduced
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> memory
>>>>>>>>>>>>>> footprint
>>>>>>>>>>>>>> or
>>>>>>>>>>>>>> if
>>>>>>>>>>>>>> it's
>>>>>>>>>>>>>> almost
>>>>>>>>>>>>>> like
>>>>>>>>>>>>>> before.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2013/8/28
>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>> Lubke
>>>>>>>>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> At
>>>>>>>>>>>>>> this
>>>>>>>>>>>>>> point
>>>>>>>>>>>>>> in
>>>>>>>>>>>>>> time,
>>>>>>>>>>>>>> as
>>>>>>>>>>>>>> far
>>>>>>>>>>>>>> as
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> SSL
>>>>>>>>>>>>>> buffer
>>>>>>>>>>>>>> allocation
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> concerned,
>>>>>>>>>>>>>> it's
>>>>>>>>>>>>>> untunable.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> That
>>>>>>>>>>>>>> said,
>>>>>>>>>>>>>> feel
>>>>>>>>>>>>>> free
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> open
>>>>>>>>>>>>>> a feature
>>>>>>>>>>>>>> request.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> As
>>>>>>>>>>>>>> to
>>>>>>>>>>>>>> your
>>>>>>>>>>>>>> second
>>>>>>>>>>>>>> question,
>>>>>>>>>>>>>> there
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> no
>>>>>>>>>>>>>> suggested
>>>>>>>>>>>>>> size.
>>>>>>>>>>>>>> This
>>>>>>>>>>>>>> is
>>>>>>>>>>>>>> all
>>>>>>>>>>>>>> very
>>>>>>>>>>>>>> application
>>>>>>>>>>>>>> specific.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'm
>>>>>>>>>>>>>> curious,
>>>>>>>>>>>>>> how
>>>>>>>>>>>>>> large
>>>>>>>>>>>>>> of
>>>>>>>>>>>>>> a file
>>>>>>>>>>>>>> are
>>>>>>>>>>>>>> you
>>>>>>>>>>>>>> sending?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I have
>>>>>>>>>>>>>>> seen
>>>>>>>>>>>>>>> a lot
>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>> buffers
>>>>>>>>>>>>>>> which
>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>> a size
>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>> 33842
>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> limit
>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>> near
>>>>>>>>>>>>>>> half
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> capacity.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Perhaps
>>>>>>>>>>>>>>> there's
>>>>>>>>>>>>>>> a way
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> tune
>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>> buffer
>>>>>>>>>>>>>>> size
>>>>>>>>>>>>>>> so
>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>> consumes
>>>>>>>>>>>>>>> less
>>>>>>>>>>>>>>> memory?
>>>>>>>>>>>>>>> Is
>>>>>>>>>>>>>>> there
>>>>>>>>>>>>>>> an
>>>>>>>>>>>>>>> ideal
>>>>>>>>>>>>>>> Buffer
>>>>>>>>>>>>>>> size
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> send
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> feed
>>>>>>>>>>>>>>> method?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> 2013/8/28
>>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>>> Lubke
>>>>>>>>>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>> reviewing
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> PR
>>>>>>>>>>>>>>> today,
>>>>>>>>>>>>>>> thanks
>>>>>>>>>>>>>>> again!
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Regarding
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> OOM:
>>>>>>>>>>>>>>> as
>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>> stands
>>>>>>>>>>>>>>> now,
>>>>>>>>>>>>>>> for
>>>>>>>>>>>>>>> each
>>>>>>>>>>>>>>> new
>>>>>>>>>>>>>>> buffer
>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>> passed
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> SSLFilter,
>>>>>>>>>>>>>>> we
>>>>>>>>>>>>>>> allocate
>>>>>>>>>>>>>>> a buffer
>>>>>>>>>>>>>>> twice
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> size
>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>> order
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> accommodate
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> encrypted
>>>>>>>>>>>>>>> result.
>>>>>>>>>>>>>>> So
>>>>>>>>>>>>>>> there's
>>>>>>>>>>>>>>> an
>>>>>>>>>>>>>>> increase.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Depending
>>>>>>>>>>>>>>> on
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> socket
>>>>>>>>>>>>>>> configurations
>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>> both
>>>>>>>>>>>>>>> endpoints,
>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>> how
>>>>>>>>>>>>>>> fast
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> remote
>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>> reading
>>>>>>>>>>>>>>> data,
>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>> could
>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> write
>>>>>>>>>>>>>>> queue
>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>> becoming
>>>>>>>>>>>>>>> too
>>>>>>>>>>>>>>> large.
>>>>>>>>>>>>>>> We
>>>>>>>>>>>>>>> do
>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>> a way
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> detect
>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>> situation,
>>>>>>>>>>>>>>> but
>>>>>>>>>>>>>>> I'm
>>>>>>>>>>>>>>> pretty
>>>>>>>>>>>>>>> sure
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> Grizzly
>>>>>>>>>>>>>>> internals
>>>>>>>>>>>>>>> are
>>>>>>>>>>>>>>> currently
>>>>>>>>>>>>>>> shielded
>>>>>>>>>>>>>>> here.
>>>>>>>>>>>>>>> I will
>>>>>>>>>>>>>>> see
>>>>>>>>>>>>>>> what
>>>>>>>>>>>>>>> I can
>>>>>>>>>>>>>>> do
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> allow
>>>>>>>>>>>>>>> users
>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>> leverage
>>>>>>>>>>>>>>> this.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Hello,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I've
>>>>>>>>>>>>>>>> made
>>>>>>>>>>>>>>>> my
>>>>>>>>>>>>>>>> pull
>>>>>>>>>>>>>>>> request.
>>>>>>>>>>>>>>>> https://github.com/AsyncHttpClient/async-http-client/pull/367
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> With
>>>>>>>>>>>>>>>> my
>>>>>>>>>>>>>>>> usecase
>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>> works,
>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>> uploaded
>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>> before.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> But
>>>>>>>>>>>>>>>> I didn't
>>>>>>>>>>>>>>>> notice
>>>>>>>>>>>>>>>> a big
>>>>>>>>>>>>>>>> memory
>>>>>>>>>>>>>>>> improvement.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Is
>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>> possible
>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>> SSL
>>>>>>>>>>>>>>>> doesn't
>>>>>>>>>>>>>>>> allow
>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>> stream
>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>> body
>>>>>>>>>>>>>>>> or
>>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>> that?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> In
>>>>>>>>>>>>>>>> memory,
>>>>>>>>>>>>>>>> I have
>>>>>>>>>>>>>>>> a lot
>>>>>>>>>>>>>>>> of:
>>>>>>>>>>>>>>>> - HeapByteBuffer
>>>>>>>>>>>>>>>> Which
>>>>>>>>>>>>>>>> are
>>>>>>>>>>>>>>>> hold
>>>>>>>>>>>>>>>> by
>>>>>>>>>>>>>>>> SSLUtils$3
>>>>>>>>>>>>>>>> Which
>>>>>>>>>>>>>>>> are
>>>>>>>>>>>>>>>> hold
>>>>>>>>>>>>>>>> by
>>>>>>>>>>>>>>>> BufferBuffers
>>>>>>>>>>>>>>>> Which
>>>>>>>>>>>>>>>> are
>>>>>>>>>>>>>>>> hold
>>>>>>>>>>>>>>>> by
>>>>>>>>>>>>>>>> WriteResult
>>>>>>>>>>>>>>>> Which
>>>>>>>>>>>>>>>> are
>>>>>>>>>>>>>>>> hold
>>>>>>>>>>>>>>>> by
>>>>>>>>>>>>>>>> AsyncWriteQueueRecord
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Here
>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>> an
>>>>>>>>>>>>>>>> exemple
>>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>> OOM
>>>>>>>>>>>>>>>> stacktrace:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> java.lang.OutOfMemoryError:
>>>>>>>>>>>>>>>> Java
>>>>>>>>>>>>>>>> heap
>>>>>>>>>>>>>>>> space
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> java.nio.ByteBuffer.allocate(ByteBuffer.java:331)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLUtils.allocateOutputBuffer(SSLUtils.java:342)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter$2.grow(SSLBaseFilter.java:117)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.ensureBufferSize(SSLConnectionContext.java:392)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrap(SSLConnectionContext.java:272)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLConnectionContext.wrapAll(SSLConnectionContext.java:227)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.wrapAll(SSLBaseFilter.java:404)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLBaseFilter.handleWrite(SSLBaseFilter.java:319)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLFilter.accurateWrite(SSLFilter.java:255)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ssl.SSLFilter.handleWrite(SSLFilter.java:143)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider$SwitchingSSLFilter.handleWrite(GrizzlyAsyncHttpProvider.java:2503)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:111)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:853)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:720)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.flushQueue(FeedableBodyGenerator.java:132)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.client.providers.grizzly.FeedableBodyGenerator.feed(FeedableBodyGenerator.java:101)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.client.providers.grizzly.MultipartBodyGeneratorFeeder$FeedBodyGeneratorOutputStream.write(MultipartBodyGeneratorFeeder.java:222)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> java.io.BufferedOutputStream.write(BufferedOutputStream.java:126)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.multipart.FilePart.sendData(FilePart.java:179)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.multipart.Part.send(Part.java:331)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.multipart.Part.sendParts(Part.java:397)
>>>>>>>>>>>>>>>> at
>>>>>>>>>>>>>>>> com.ning.http.client.providers.grizzly.MultipartBodyGeneratorFeeder.feed(MultipartBodyGeneratorFeeder.java:144)
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Any
>>>>>>>>>>>>>>>> idea?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> 2013/8/27
>>>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>>>> Lubke
>>>>>>>>>>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Excellent!
>>>>>>>>>>>>>>>> Looking
>>>>>>>>>>>>>>>> forward
>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>> pull
>>>>>>>>>>>>>>>> request!
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>>>>> thanks,
>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>> works
>>>>>>>>>>>>>>>>> fine,
>>>>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>>>>> make
>>>>>>>>>>>>>>>>> a pull
>>>>>>>>>>>>>>>>> request
>>>>>>>>>>>>>>>>> on
>>>>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>>>>> tomorrow
>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>> a better
>>>>>>>>>>>>>>>>> code
>>>>>>>>>>>>>>>>> using
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> same
>>>>>>>>>>>>>>>>> Part
>>>>>>>>>>>>>>>>> classes
>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>> already
>>>>>>>>>>>>>>>>> exist.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> I created
>>>>>>>>>>>>>>>>> an
>>>>>>>>>>>>>>>>> OutputStream
>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>> redirects
>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> BodyGenerator
>>>>>>>>>>>>>>>>> feeder.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> The
>>>>>>>>>>>>>>>>> problem
>>>>>>>>>>>>>>>>> I currently
>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> feeder
>>>>>>>>>>>>>>>>> feeds
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> queue
>>>>>>>>>>>>>>>>> faster
>>>>>>>>>>>>>>>>> than
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> async
>>>>>>>>>>>>>>>>> thread
>>>>>>>>>>>>>>>>> polling
>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>> :)
>>>>>>>>>>>>>>>>> I need
>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>> expose
>>>>>>>>>>>>>>>>> a limit
>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>> queue
>>>>>>>>>>>>>>>>> size
>>>>>>>>>>>>>>>>> or
>>>>>>>>>>>>>>>>> something,
>>>>>>>>>>>>>>>>> will
>>>>>>>>>>>>>>>>> work
>>>>>>>>>>>>>>>>> on
>>>>>>>>>>>>>>>>> that,
>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>> will
>>>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>>>> better
>>>>>>>>>>>>>>>>> than
>>>>>>>>>>>>>>>>> a thread
>>>>>>>>>>>>>>>>> sleep
>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>> slow
>>>>>>>>>>>>>>>>> down
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> filepart
>>>>>>>>>>>>>>>>> reading
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> 2013/8/27
>>>>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>>>>> Lubke
>>>>>>>>>>>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Yes,
>>>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>>> that.
>>>>>>>>>>>>>>>>> I was
>>>>>>>>>>>>>>>>> going
>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>> tackle
>>>>>>>>>>>>>>>>> adding
>>>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>>>> today.
>>>>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>>>>> follow
>>>>>>>>>>>>>>>>> up
>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>>>> you
>>>>>>>>>>>>>>>>> can
>>>>>>>>>>>>>>>>> test
>>>>>>>>>>>>>>>>> out.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Ok
>>>>>>>>>>>>>>>>>> thanks!
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> I think
>>>>>>>>>>>>>>>>>> I see
>>>>>>>>>>>>>>>>>> what
>>>>>>>>>>>>>>>>>> I could
>>>>>>>>>>>>>>>>>> do,
>>>>>>>>>>>>>>>>>> probably
>>>>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>>>> that:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> FeedableBodyGenerator
>>>>>>>>>>>>>>>>>> bodyGenerator
>>>>>>>>>>>>>>>>>> = new
>>>>>>>>>>>>>>>>>> FeedableBodyGenerator();
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> MultipartBodyGeneratorFeeder
>>>>>>>>>>>>>>>>>> bodyGeneratorFeeder
>>>>>>>>>>>>>>>>>> = new
>>>>>>>>>>>>>>>>>> MultipartBodyGeneratorFeeder(bodyGenerator);
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Request
>>>>>>>>>>>>>>>>>> uploadRequest1
>>>>>>>>>>>>>>>>>> = new
>>>>>>>>>>>>>>>>>> RequestBuilder("POST")
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> .setUrl("url")
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> .setBody(bodyGenerator)
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> .build();
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> ListenableFuture<Response>
>>>>>>>>>>>>>>>>>> asyncRes
>>>>>>>>>>>>>>>>>> = asyncHttpClient
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> .prepareRequest(uploadRequest1)
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> .execute(new
>>>>>>>>>>>>>>>>>> AsyncCompletionHandlerBase());
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> bodyGeneratorFeeder.append("param1","value1");
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> bodyGeneratorFeeder.append("param2","value2");
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> bodyGeneratorFeeder.append("fileToUpload",fileInputStream);
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> bodyGeneratorFeeder.end();
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Response
>>>>>>>>>>>>>>>>>> uploadResponse
>>>>>>>>>>>>>>>>>> = asyncRes.get();
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Does
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> seem
>>>>>>>>>>>>>>>>>> ok
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> you?
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> I guess
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> could
>>>>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>>>>> interesting
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> provide
>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>> MultipartBodyGeneratorFeeder
>>>>>>>>>>>>>>>>>> class
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>>>>>> or
>>>>>>>>>>>>>>>>>> Grizzly
>>>>>>>>>>>>>>>>>> since
>>>>>>>>>>>>>>>>>> some
>>>>>>>>>>>>>>>>>> other
>>>>>>>>>>>>>>>>>> people
>>>>>>>>>>>>>>>>>> may
>>>>>>>>>>>>>>>>>> want
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> achieve
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> same
>>>>>>>>>>>>>>>>>> thing
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> 2013/8/26
>>>>>>>>>>>>>>>>>> Ryan
>>>>>>>>>>>>>>>>>> Lubke
>>>>>>>>>>>>>>>>>> <ryan.lubke_at_oracle.com
>>>>>>>>>>>>>>>>>> <mailto:ryan.lubke_at_oracle.com>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Sébastien
>>>>>>>>>>>>>>>>>> Lorber
>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Hello,
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> I would
>>>>>>>>>>>>>>>>>> like
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> know
>>>>>>>>>>>>>>>>>> if
>>>>>>>>>>>>>>>>>> it's
>>>>>>>>>>>>>>>>>> possible
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> upload
>>>>>>>>>>>>>>>>>> a file
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>>>>>> / Grizzly
>>>>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>>>>> streaming,
>>>>>>>>>>>>>>>>>> I mean
>>>>>>>>>>>>>>>>>> without
>>>>>>>>>>>>>>>>>> loading
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> whole
>>>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>>>> bytes
>>>>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>>>>> memory.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> The
>>>>>>>>>>>>>>>>>> default
>>>>>>>>>>>>>>>>>> behavior
>>>>>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> allocate
>>>>>>>>>>>>>>>>>> a byte[]
>>>>>>>>>>>>>>>>>> which
>>>>>>>>>>>>>>>>>> contans
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> whole
>>>>>>>>>>>>>>>>>> file,
>>>>>>>>>>>>>>>>>> so
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> means
>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>> my
>>>>>>>>>>>>>>>>>> server
>>>>>>>>>>>>>>>>>> can
>>>>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>>>>> OOM
>>>>>>>>>>>>>>>>>> if
>>>>>>>>>>>>>>>>>> too
>>>>>>>>>>>>>>>>>> many
>>>>>>>>>>>>>>>>>> users
>>>>>>>>>>>>>>>>>> upload
>>>>>>>>>>>>>>>>>> a large
>>>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> same
>>>>>>>>>>>>>>>>>> time.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> I've
>>>>>>>>>>>>>>>>>> tryied
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> a Heap
>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>> ByteBuffer
>>>>>>>>>>>>>>>>>> memory
>>>>>>>>>>>>>>>>>> managers,
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> reallocate=true/false
>>>>>>>>>>>>>>>>>> but
>>>>>>>>>>>>>>>>>> no
>>>>>>>>>>>>>>>>>> more
>>>>>>>>>>>>>>>>>> success.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> It
>>>>>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> whole
>>>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>>>> content
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> appended
>>>>>>>>>>>>>>>>>> wto
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> BufferOutputStream,
>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>> then
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> underlying
>>>>>>>>>>>>>>>>>> buffer
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> written.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> At
>>>>>>>>>>>>>>>>>> least
>>>>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>>>>> seems
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> case
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>>>>>> integration:
>>>>>>>>>>>>>>>>>> https://github.com/AsyncHttpClient/async-http-client/blob/6faf1f316e5546110b0779a5a42fd9d03ba6bc15/providers/grizzly/src/main/java/org/asynchttpclient/providers/grizzly/bodyhandler/PartsBodyHandler.java
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> So,
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> there
>>>>>>>>>>>>>>>>>> a way
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> patch
>>>>>>>>>>>>>>>>>> AHC
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> stream
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>>>> so
>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>> I could
>>>>>>>>>>>>>>>>>> eventually
>>>>>>>>>>>>>>>>>> consume
>>>>>>>>>>>>>>>>>> only
>>>>>>>>>>>>>>>>>> 20mo
>>>>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>>>>> heap
>>>>>>>>>>>>>>>>>> while
>>>>>>>>>>>>>>>>>> uploading
>>>>>>>>>>>>>>>>>> a 500mo
>>>>>>>>>>>>>>>>>> file?
>>>>>>>>>>>>>>>>>> Or
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>>>>> simply
>>>>>>>>>>>>>>>>>> impossible
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> Grizzly?
>>>>>>>>>>>>>>>>>> I didn't
>>>>>>>>>>>>>>>>>> notice
>>>>>>>>>>>>>>>>>> anything
>>>>>>>>>>>>>>>>>> related
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> documentation.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> It's
>>>>>>>>>>>>>>>>>> possible
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> FeedableBodyGenerator.
>>>>>>>>>>>>>>>>>> But
>>>>>>>>>>>>>>>>>> if
>>>>>>>>>>>>>>>>>> you're
>>>>>>>>>>>>>>>>>> tied
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> using
>>>>>>>>>>>>>>>>>> Multipart
>>>>>>>>>>>>>>>>>> uploads,
>>>>>>>>>>>>>>>>>> you'd
>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> convert
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> multipart
>>>>>>>>>>>>>>>>>> data
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> Buffers
>>>>>>>>>>>>>>>>>> manually
>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>> send
>>>>>>>>>>>>>>>>>> using
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> FeedableBodyGenerator.
>>>>>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>>>>>> take
>>>>>>>>>>>>>>>>>> a closer
>>>>>>>>>>>>>>>>>> look
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> see
>>>>>>>>>>>>>>>>>> if
>>>>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>>>>> area
>>>>>>>>>>>>>>>>>> can
>>>>>>>>>>>>>>>>>> be
>>>>>>>>>>>>>>>>>> improved.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Btw
>>>>>>>>>>>>>>>>>> in
>>>>>>>>>>>>>>>>>> my
>>>>>>>>>>>>>>>>>> case
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> a file
>>>>>>>>>>>>>>>>>> upload.
>>>>>>>>>>>>>>>>>> I receive
>>>>>>>>>>>>>>>>>> a file
>>>>>>>>>>>>>>>>>> with
>>>>>>>>>>>>>>>>>> CXF
>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> transmit
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> a storage
>>>>>>>>>>>>>>>>>> server
>>>>>>>>>>>>>>>>>> (like
>>>>>>>>>>>>>>>>>> S3).
>>>>>>>>>>>>>>>>>> CXF
>>>>>>>>>>>>>>>>>> doesn't
>>>>>>>>>>>>>>>>>> consume
>>>>>>>>>>>>>>>>>> memory
>>>>>>>>>>>>>>>>>> bevause
>>>>>>>>>>>>>>>>>> it
>>>>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>>>>> streaming
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> large
>>>>>>>>>>>>>>>>>> fle
>>>>>>>>>>>>>>>>>> uploads
>>>>>>>>>>>>>>>>>> to
>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>> file
>>>>>>>>>>>>>>>>>> system,
>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>> then
>>>>>>>>>>>>>>>>>> provides
>>>>>>>>>>>>>>>>>> an
>>>>>>>>>>>>>>>>>> input
>>>>>>>>>>>>>>>>>> stream
>>>>>>>>>>>>>>>>>> on
>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>> file.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Thanks
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>
>>
>>
>>
>