You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-user@ws.apache.org by "Lee J. Willwerth" <lw...@redseaco.com> on 2001/06/06 23:40:53 UTC

Slow performance with large strings

Hello all,
I have a soap based application that returns the contents of a server
side file upon request.  It is deployed using apache soap 2.0 on tomcat
3.2.1.  The contents of the file are returned as a String from the
method I am calling.  My problem is this. This scheme seems to work well
as long as the files are say less than 50 kb. A 50 kb file is returned
in less than 2 seconds.   However, as the file size increases, the time
for the return trip increases greatly.  An 85 kb file takes 13 seconds
and a 170 kb file takes 67 seconds.  All of this additional time occurs
between the time my method returns the String and the time the client
receives the reply.  Obviously, this time increase is not linear with
the file size and is causing considerable performance problems.  Has
anyone run into this issue and if so, do you know what is causing it?  I
can certainly upgrade my application to soap 2.2 but I don't want to do
that if it isn't going to fix the problem. Thanks in advance for your
help!

--
Regards,

Lee J. Willwerth
Redsea Works Co.
1-888-891-5707


Re: Slow performance with large strings

Posted by Tom Myers <to...@dreamscape.com>.
At 05:40 PM 6/6/2001 -0400, Lee J. Willwerth wrote:
>Hello all,
>I have a soap based application that returns the contents of a server
>side file upon request.  It is deployed using apache soap 2.0 on tomcat
>3.2.1.  The contents of the file are returned as a String from the
>method I am calling.  My problem is this. This scheme seems to work well
>as long as the files are say less than 50 kb. A 50 kb file is returned
>in less than 2 seconds.   However, as the file size increases, the time
>for the return trip increases greatly.  An 85 kb file takes 13 seconds
>and a 170 kb file takes 67 seconds.  .......

I dunno, but it looks to me as if the basic 
   org.apache.soap.encoding.SOAPMappingRegistry is passing this through
---------------------
Serializer cleanSer = new Serializer()
   {
     public void marshall(String inScopeEncStyle, Class javaType, Object src,
                          Object context, Writer sink, NSStack nsStack,
                          XMLJavaMappingRegistry xjmr, SOAPContext ctx)
       throws IllegalArgumentException, IOException {
       nsStack.pushScope();

       SoapEncUtils.generateStructureHeader(inScopeEncStyle,
                                            javaType,
                                            context,
                                            sink,
                                            nsStack,
                                            xjmr);

       sink.write(Utils.cleanString(src.toString()) + "</" + context + '>');

       nsStack.popScope();
     }
   };
---------------------
and that seems to be the String.class serializer by default.
so it gets passed to "cleanString" and then we append three times, each
time allocating a new and slightly larger buffer? and cleanString itself is
--------------------
   public static String cleanString(String orig)
...
     StringBuffer strBuf = new StringBuffer();
     char[] chars = orig.toCharArray();

     for (int i = 0; i < chars.length; i++)
     {
       switch (chars[i])
       {
         case '&'  : strBuf.append("&amp;");
                     break;
         case '\"' : strBuf.append("&quot;");
...
         default   : strBuf.append(chars[i]);
                     break;
--------------------
and this is very clean code, but the system is gonna start out with a tiny
StringBuffer and reallocate many many times. So that could easily be the
source of a nonlinear cost of the source you describe, yes? If so, then 
you make some test files with no chars in the string &"'<>, so you won't
confuse the parser at the other end, and you apply a serializer that just
passes that string through, a class something like so:
----
   public class RawSerializer implements Serializer {
     public void marshall(String inScopeEncStyle, Class javaType, Object src,
                          Object context, Writer sink, NSStack nsStack,
                          XMLJavaMappingRegistry xjmr, SOAPContext ctx)
       throws IllegalArgumentException, IOException {
       nsStack.pushScope();

       SoapEncUtils.generateStructureHeader(inScopeEncStyle,
                                            javaType,
                                            context,
                                            sink,
                                            nsStack,
                                            xjmr);

       sink.write(src.toString());
       sink.write("</");
       sink.write(context);
       sink.write(">");

       nsStack.popScope();
     }
}
---
well, something like that. And then in your deploymentDescriptor.xml you say
   <isd:mappings>
     <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:x="urn:xml-soap-demo-whatever" qname="x:string"
              javaType="java.lang.String"
              java2XMLClassName="RawSerializer"
              xml2JavaClassName="org.apache.soap.encoding.soapenc.StringDeserializer"/>
   </isd:mappings>    

or some such (with xml-soap-demo-whatever replaced by your actual urn) and either 
this works better or it doesn't. If it doesn't, then I have made my 3,913th mistake
of the day, which is not a surprise. If it does, then you think about how to cleanString
without so much reallocation, either doing lots of little sink.writes in a loop,
or preallocate a big StringBuffer. Or something.

Tom Myers


---------------------------------------------------------------------
To unsubscribe, e-mail: soap-user-unsubscribe@xml.apache.org
For additional commands, email: soap-user-help@xml.apache.org


Re: Slow performance with large strings

Posted by Tom Myers <to...@dreamscape.com>.
At 05:40 PM 6/6/2001 -0400, Lee J. Willwerth wrote:
>Hello all,
>I have a soap based application that returns the contents of a server
>side file upon request.  It is deployed using apache soap 2.0 on tomcat
>3.2.1.  The contents of the file are returned as a String from the
>method I am calling.  My problem is this. This scheme seems to work well
>as long as the files are say less than 50 kb. A 50 kb file is returned
>in less than 2 seconds.   However, as the file size increases, the time
>for the return trip increases greatly.  An 85 kb file takes 13 seconds
>and a 170 kb file takes 67 seconds.  .......

I dunno, but it looks to me as if the basic 
   org.apache.soap.encoding.SOAPMappingRegistry is passing this through
---------------------
Serializer cleanSer = new Serializer()
   {
     public void marshall(String inScopeEncStyle, Class javaType, Object src,
                          Object context, Writer sink, NSStack nsStack,
                          XMLJavaMappingRegistry xjmr, SOAPContext ctx)
       throws IllegalArgumentException, IOException {
       nsStack.pushScope();

       SoapEncUtils.generateStructureHeader(inScopeEncStyle,
                                            javaType,
                                            context,
                                            sink,
                                            nsStack,
                                            xjmr);

       sink.write(Utils.cleanString(src.toString()) + "</" + context + '>');

       nsStack.popScope();
     }
   };
---------------------
and that seems to be the String.class serializer by default.
so it gets passed to "cleanString" and then we append three times, each
time allocating a new and slightly larger buffer? and cleanString itself is
--------------------
   public static String cleanString(String orig)
...
     StringBuffer strBuf = new StringBuffer();
     char[] chars = orig.toCharArray();

     for (int i = 0; i < chars.length; i++)
     {
       switch (chars[i])
       {
         case '&'  : strBuf.append("&amp;");
                     break;
         case '\"' : strBuf.append("&quot;");
...
         default   : strBuf.append(chars[i]);
                     break;
--------------------
and this is very clean code, but the system is gonna start out with a tiny
StringBuffer and reallocate many many times. So that could easily be the
source of a nonlinear cost of the source you describe, yes? If so, then 
you make some test files with no chars in the string &"'<>, so you won't
confuse the parser at the other end, and you apply a serializer that just
passes that string through, a class something like so:
----
   public class RawSerializer implements Serializer {
     public void marshall(String inScopeEncStyle, Class javaType, Object src,
                          Object context, Writer sink, NSStack nsStack,
                          XMLJavaMappingRegistry xjmr, SOAPContext ctx)
       throws IllegalArgumentException, IOException {
       nsStack.pushScope();

       SoapEncUtils.generateStructureHeader(inScopeEncStyle,
                                            javaType,
                                            context,
                                            sink,
                                            nsStack,
                                            xjmr);

       sink.write(src.toString());
       sink.write("</");
       sink.write(context);
       sink.write(">");

       nsStack.popScope();
     }
}
---
well, something like that. And then in your deploymentDescriptor.xml you say
   <isd:mappings>
     <isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:x="urn:xml-soap-demo-whatever" qname="x:string"
              javaType="java.lang.String"
              java2XMLClassName="RawSerializer"
              xml2JavaClassName="org.apache.soap.encoding.soapenc.StringDeserializer"/>
   </isd:mappings>    

or some such (with xml-soap-demo-whatever replaced by your actual urn) and either 
this works better or it doesn't. If it doesn't, then I have made my 3,913th mistake
of the day, which is not a surprise. If it does, then you think about how to cleanString
without so much reallocation, either doing lots of little sink.writes in a loop,
or preallocate a big StringBuffer. Or something.

Tom Myers


---------------------------------------------------------------------
To unsubscribe, e-mail: soap-user-unsubscribe@xml.apache.org
For additional commands, email: soap-user-help@xml.apache.org