You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@axis.apache.org by Piergiuliano Bossi <P....@quinary.com> on 2005/02/09 11:26:14 UTC
Re: unexpected attachment performance ==> SOLVED!
Hello all,
it's 2 months since my last message, but finally we have got to be able
to conduct new load tests in production (customer's machines were too
busy in this period). Results are good as expected and customer is
satisfied (view it at fixed width, ramp-up 200ms):
n.thread Average Min Max Error Rate Client Max heap
5 3692 2556 4505 0.00% 1.1/sec 512Mb
5 4929 4819 5107 0.00% 58.7/min 512Mb
10 6439 6117 6738 0.00% 1.5/sec 512Mb
10 6026 5381 6734 0.00% 1.5/sec 512Mb
20 11017 9175 13134 0.00% 1.5/sec 512Mb
20 9657 6915 11465 0.00% 1.7/sec 512Mb
30 12004 7670 15437 0.00% 1.6/sec 512Mb
30 12815 9539 16167 0.00% 1.7/sec 512Mb
40 18497 11049 25532 0.00% 1.5/sec 512Mb
40 14276 9369 18820 0.00% 1.7/sec 512Mb
50 18711 10665 26607 0.00% 1.6/sec 512Mb
50 18896 9441 25013 0.00% 1.6/sec 512Mb
Comparing these results (custom buffer implementation) with byte[]
parameter shows an improvement in performance between 3 and 5 times,
while comparing with unbuffered attachments is between 7 and 12 times.
You should also note that the unbuffered version is in reality buffered:
when asked for returning a stream to read attachments, axis implements a
stream that is basically buffered, but implementing a custom buffer
shows an order of magnitude of improvement.
Ciao, Giuliano
Piergiuliano Bossi wrote:
> After some more thoughts it looks that we are not doing buffered I/O
> while reading the attachment from disk. As suggested in many places
> (for example
> http://java.sun.com/docs/books/performance/1st_edition/html/JPIOPerformance.fm.html)
> I/O operations in java are by default unbuffered.
>
> Shame on us! :(
>
> Preliminary measures taken on development workstation show an order of
> magnitude of improvement.
> Hopefully tomorrow we will get better results on servers and under
> load as well.
>
> Cheers,
> Giuliano
>
> Piergiuliano Bossi wrote:
>
>> Hello all,
>>
>> one year ago we have developed a web service that has a few
>> parameters, one of which is a byte[]. At that time this parameter was
>> used to get a binary file (for example midi or gif) with size up to
>> 150 KB (max). We have had excellent results, both in terms of
>> reliability and speed.
>> Customer's needs have grown since then and today we are working with
>> files that can be 4 MB in size. Of course, we have looked at
>> attachments for this (check thread
>> http://marc.theaimsgroup.com/?l=axis-user&m=109707110706202&w=2).
>> Now our web service looks for the binary file in the byte array
>> parameter first, and then into attachments. The idea is that if the
>> file is small (ie: 100 KB) then using the parameter is ok, otherwise
>> the attachment got to be used.
>>
>> The problem is that we observe unexpected performance in production.
>> We have built some jmeter load tests, trying to send 4 MB content
>> with or without using attachments, 5 or 10 concurrent client threads
>> (no ramp-up period) and we get the following results (please watch it
>> at fixed width):
>> thread Average Min Max Error Attachments
>> 5 14889 13373 16205 0.00% no
>> 5 32170 31282 33438 0.00% yes
>> 10 31673 31547 31857 0.00% no
>> 10 45556 41563 51975 0.00% yes
>>
>> These measures are "round-trip", taken from client-side.
>>
>> As you can see it seems that without attachments performances are
>> better! This contradicts everything we have read so far and even
>> logic too.
>>
>> Please, note that production architecture is structured in this way:
>> *) there are 2 servers, each with Red Hat Linux rel 8.0 (kernel
>> 2.4.18-14smp), 4 microproc. Intel Xeon 550 MHz, 1 GB RAM
>> *) each server is using a 1.4.2_06 jvm, tomcat 4.1.30 and axis 1.1
>> *) in front of the servers there is an Alteon balancer
>>
>> Load tests were performed using a fast client machine, a Sun Solaris
>> 220, double-processor with 2 GB RAM, therefore we expect that the
>> problem doesn't lie on client side.
>>
>> Before implementing attachments we have profiled a single request
>> with a 4 MB file (passed as a byte[]) to our web service (with
>> OptimizeIT) and we have discovered that our business logic was
>> consuming 19.2% of cpu time: the remining part was consumed by axis
>> in various ways, for example retrieving the Envelope
>> (org.apache.axis.Message.getSOAPEnvelope) and getting parameters in
>> java objects (org.apache.axis.message.RPCElement.getParams)
>>
>> We have not profiled current implementation with attachments yet, but
>> we will do it soon. Let's see if there will be any surprise.
>>
>> Real problem is that we should be able to have a round-trip max
>> period well under 10 seconds under more than 10 concurrent threads on
>> client side.
>>
>> What do you think about it? How can we explain those numbers? Is
>> there any way to improve significantly these performance results?
>>
>> We are considering passing the file over the filesystem, getting path
>> only into the web service, but this is a last chance that we prefer
>> to avoid, because it assumes that client and server share a
>> filesystem somewhere.
>>
>> TIA
>> Giuliano
>>
>>
>> PS: a couple of snippets of code (client side is used in load tests)
>>
>> ********************CUT HERE - CLIENT SIDE********************
>> /**This class should store all attachment data in memory */
>> static class MemoryOnlyDataSource extends
>> org.apache.axis.attachments.ManagedMemoryDataSource{
>>
>> MemoryOnlyDataSource( byte [] in, String contentType) throws
>> java.io.IOException{
>> super( new java.io.ByteArrayInputStream(in) , Integer.MAX_VALUE
>> -2, contentType, true);
>> }
>> MemoryOnlyDataSource( String in, String contentType)throws
>> java.io.IOException{
>> this( in.getBytes() , contentType);
>> }
>> }
>>
>> service._setProperty(Call.ATTACHMENT_ENCAPSULATION_FORMAT,
>> Call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME);
>> service.setTimeout(60*60*1000);
>>
>> DataHandler attachment = new DataHandler(new
>> MemoryOnlyDataSource(aContentAsAttachment, mimeType));
>> service.addAttachment(attachment);
>>
>> byte[] contentData = null; // if null, then attachments are used
>> service.insertContent(param1, param2, param3, param4, param5,
>> contentData, param6, param7, param8);
>> ********************CUT HERE - CLIENT SIDE********************
>>
>> ********************CUT HERE - SERVER SIDE********************
>> public int insertContent(String param1, String param2, String param3,
>> String param4, String param5, byte[] contentData, int param6, boolean
>> param7, StringHolder param8)
>> {
>> if (contentData == null)
>> {
>> try
>> {
>> AttachmentPart messageAttachment = getmessageAttachment();
>> if (messageAttachment != null)
>> contentData = toByteArray(messageAttachment);
>> }
>> catch (Exception e)
>> {
>> // ...
>> }
>> }
>> // ... business logic here ...
>> }
>>
>> private AttachmentPart getmessageAttachment() throws AxisFault
>> {
>> MessageContext msgContext = MessageContext.getCurrentContext();
>> Message reqMsg = msgContext.getRequestmessage();
>> Attachments allAttachments = reqMsg.getAttachmentsImpl();
>>
>> AttachmentPart attachment = null;
>> if (allAttachments == null)
>> // ...
>> else if (allAttachments.getAttachmentCount() > 0)
>> attachment =
>> (AttachmentPart)allAttachments.getAttachments().iterator().next();
>> return attachment;
>> } private byte[] toByteArray(AttachmentPart attachment) throws
>> SOAPException, IOException
>> {
>> ByteArrayOutputStream outputStream = new
>> ByteArrayOutputStream(attachment.getSize());
>> InputStream inputStream = (InputStream) attachment.getContent();
>> int currentByte = -1;
>> while ((currentByte = inputStream.read()) != -1)
>> outputStream.write(currentByte);
>>
>> inputStream.close();
>> outputStream.close();
>>
>> return outputStream.toByteArray();
>> } ********************CUT HERE - SERVER SIDE********************
>>
>>
>