You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Daniel Hagen <dh...@h1-software.de> on 2007/07/25 18:45:34 UTC

Performance problem on HTTP PUT of large binary data

Dear All,

I am currently developing an application that handles uploads of big files using HTTP PUT.
The I/O part of the server application can be broken down to (not literally spoken, just to make the working clear):

public void doPut(HttpServletRequest request, HttpServletResponse response)
{
     InputStream in = request.getInputStream();
     OutputStream out = new FileOutputStream("some_file");
     [Transfer data between streams using a 32K buffer]
}

The client is a Java client writing 32K blocks to the server using chunked streaming mode with 32K chunk size.

On performance tests I noticed the CPU load of the server going up to 100% and remaining there during the complete upload.
I did some further profiling and finally got one (in my eyes) very propable candidate:
The read(byte[]) methods of the (Coyote)InputStream return only blocks of ~1000 to ~7500 bytes resulting in an excessive amount of calls to the aforementioned methods in the process.
 (Windows & Linux alike, same behavior when accessing localhost or on access over network, c++ libcurl client produces the same pattern).
The delay between the calls also does not seem to matter since the blocks to not get larger even with a 1 second or larger delay between the calls to InputStream.read(byte[]).

I also noticed a funny pattern in the number of bytes read, there seems to be a fixed maximum of ~7000 bytes (windows) and a similar but not equal number (~7700) on linux.

I tested with Tomcat 6.0.13 accessing the Tomcat HTTP connector directly, the connector was configured with:
[...]
              socket.appReadBufSize="32678"
              socket.appWriteBufferSize="32768"
              socket.rxBufSize="32678"

(BTW, Tomcat 5.5 behavior is the same)

So finally my question:

Do you have any idea what could cause the described behavior and prevent the server from returning larger buffers?
Any parameters I could check/tweek to overcome that problem?

Thank you!

Daniel


---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Performance problem on HTTP PUT of large binary data

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chuck,

Caldarale, Charles R wrote:
>> From: Christopher Schultz [mailto:chris@christopherschultz.net] 
>> Subject: Re: Performance problem on HTTP PUT of large binary data
>>
>> - From java.io.InputStream javadoc:
>> "Reads some number of bytes from the input stream and stores 
>> them into the buffer array b. The number of bytes actually
>> read is returned as an integer. This method blocks until
>> input data is available, end of file is detected, or an
>> exception is thrown."
>>
>> To me, that's a little vague.
> 
> That's because InputStream is an abstract class; the actual behavior is
> dependent on whatever concrete class is instantiated behind the method
> definition.

Of course. What I was trying to point out was that simply using a 32k
byte array doesn't mean that each call to InputStream.read(byte[]) would
return a full buffer. ServletOutputStream doesn't add anything to the
Java API's documentation, so you can make no further assumptions.

- -chris

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD4DBQFGp6gm9CaO5/Lv0PARAhi2AJ0Y0aMAt/mkVHc8GNaneq0CY9g5YwCYoQTJ
0u19McjqofHkq/s24T+2bQ==
=FFF9
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Performance problem on HTTP PUT of large binary data

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Christopher Schultz [mailto:chris@christopherschultz.net] 
> Subject: Re: Performance problem on HTTP PUT of large binary data
> 
> - From java.io.InputStream javadoc:
> "Reads some number of bytes from the input stream and stores 
> them into the buffer array b. The number of bytes actually
> read is returned as an integer. This method blocks until
> input data is available, end of file is detected, or an
> exception is thrown."
> 
> To me, that's a little vague.

That's because InputStream is an abstract class; the actual behavior is
dependent on whatever concrete class is instantiated behind the method
definition.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Performance problem on HTTP PUT of large binary data

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Daniel,

Daniel Hagen wrote:
> I am currently developing an application that handles uploads of big 
> files using HTTP PUT.

> The client is a Java client writing 32K blocks to the server using
> chunked streaming mode with 32K chunk size.
> 
> On performance tests I noticed the CPU load of the server going up to
> 100% and remaining there during the complete upload. I did some
> further profiling and finally got one (in my eyes) very propable
> candidate: The read(byte[]) methods of the (Coyote)InputStream return
> only blocks of ~1000 to ~7500 bytes resulting in an excessive amount
> of calls to the aforementioned methods in the process.

I wonder if this is due to the IP and ethernet chunking of data.
Ethernet (and IP) packets /can/ get really big, but are often something
small like 1500 bytes or so. Your OS (or OSs) might be getting lazy and
just returning each packet in its own block.

It looks like you are using non-buffered streams. Have you tried using
BufferedInputStream? That might allow more bytes to pile up before the
bytes are actually returned. Simply using a 32k byte array doesn't
really set any chunking size when reading. The InputStream class will
just give you what's available, not block to fill your buffer entirely.

- From java.io.InputStream javadoc:
"Reads some number of bytes from the input stream and stores them into
the buffer array b. The number of bytes actually read is returned as an
integer. This method blocks until input data is available, end of file
is detected, or an exception is thrown."

To me, that's a little vague. It only says that it will block until data
is available... it doesn't say how much is required for a successful
return. I suspect that it will return immediately when any amount of
data is available.

> I also noticed a funny pattern in the number of bytes read, there
> seems to be a fixed maximum of ~7000 bytes (windows) and a similar
> but not equal number (~7700) on linux.

Sounds like a buffering issue. Try BufferedInputStream and re-test.

> Do you have any idea what could cause the described behavior and
> prevent the server from returning larger buffers? Any parameters I
> could check/tweek to overcome that problem?

I suspect that your server is fast enough to be able to steal small
amounts of data from the TCP stack each time, rather than actually
getting 32k all at once. Since you aren't buffering your input, you are
getting small bytes (ha!) of data instead of large ones.

Give buffering a try and let us know how it goes. If that doesn't so it,
you might want to look into Comet which features non-blocking IO
capability, though I'm not entirely sure how that would help you, here ;)

- -chris

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGp4l19CaO5/Lv0PARAtSSAKCRcDk/TKgC/2Lh9/ajF4caiI8DmQCgitrn
zLSzld/lfDLKjfCsqSmGWxM=
=WokQ
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org