Scott, Here is server time picture taken on the Tomcat server , processing ComplexRequest. The red ellipses show that MimePart initialization takes 10-15% of CPU load. The blue ellipses show that ContentType is also quite expensive for benefits it provide. I prepared patch for caching ContentType...
Pavel > -----Original Message----- > From: Scott Nichol [mailto:snicholnews@;scottnichol.com] > Sent: Wednesday, November 13, 2002 5:48 PM > To: [EMAIL PROTECTED] > Subject: Re: Using mime parts - huge drawbacks > > > Pavel, > > Yes, this is a good observation. In the case where there are no > attachments, the process could be streamlined by serializing directly. > I am still actively working on this part of the code > (TransportMessage, > SOAPContext, Call) and will look at sidestepping some of the activity > where there are no attachments, just a SOAP envelope, which > as you point > out is the typical scenario. > > Scott Nichol > > ----- Original Message ----- > From: "Pavel Ausianik" <[EMAIL PROTECTED]> > To: <[EMAIL PROTECTED]> > Sent: Wednesday, November 13, 2002 9:04 AM > Subject: Using mime parts - huge drawbacks > > > > Hello, > > > > thinking more on the current code I have found interesting > thing. Most > > requests we have a simple, straight SOAP envelopes, without any > attachments. > > Looking how it is processed I have found following (traced from > > httpconnection): > > > > In SOAPHTTPConnection.send() we call TransportMessage.save(). > > Let's look into it (see my comment how I understand it: > > > > String rootContentType = null; > > > > // Root Part is Not set for Simple Envelope ! > > > > if (ctx.isRootPartSet()) { > > //... Not in use for simple case > > } > > > > if (rootContentType == null) > > rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8; > > if (getEnvelope() != null) { > > > > // Now really create root part - how important it is if we > now how to > write > > this Envelope without involving Mime !!! > > > > ctx.setRootPart(envelope, rootContentType); > > } else { > > //... Not in use for simple case > > } > > > > // Print the whole response to a byte array. > > // Tracing into this code we'll found that all it will do it add > > unnecessary header to envelope > > // The headers include Content-Type - we know which is, > > // Content-id - do we need it? Even if yes we can create any id > > // Content-Transfer-Encoding - not for HTTp, anyway we force it to 8 > bit > > // Content-Lenght - easy to calculate > > > > ByteArrayOutputStream payload = > > new ByteArrayOutputStream(1024); > > ctx.writeTo(payload); > > bytes = payload.toByteArray(); > > > > // Now strip off the headers. (Grmbl, get rid of JavaMail > > // for MIME support). Just intercept the Content-Type > > // Remove headers which created right now.... > > > > .... > > > > // TODO: should not send for HTTP response > > headers.put("Accept-Encoding", "x-gzip"); > > if (Boolean.TRUE.equals(ctx.getGzip())) { > > // Deflate > > ByteArrayOutputStream baos = > > new > ByteArrayOutputStream(bytes.length > * 2); > > GZIPOutputStream gzos = new GZIPOutputStream(baos); > > gzos.write(bytes, offset, bytes.length - offset); > > gzos.close(); > > baos.close(); > > bytes = baos.toByteArray(); > > offset = 0; > > > > headers.put("Content-Encoding", "x-gzip"); > > } > > > > Seems like we are doing wonderful job of running a lot unnecessary > > operations, involving a lot of memory allocations... It > could be most > > advanced improvement we ever done! > > > > Best regards, > > Pavel > > > > > > > > -- > > To unsubscribe, e-mail: <mailto:soap-dev-unsubscribe@;xml.apache.org> > For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org> > > -- To unsubscribe, e-mail: <mailto:soap-dev-unsubscribe@;xml.apache.org> For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org>
<<attachment: untitled.GIF>>
Index: TransportMessage.java
===================================================================
RCS file:
/home/cvspublic/xml-soap/java/src/org/apache/soap/transport/TransportMessage.java,v
retrieving revision 1.19
diff -u -r1.19 TransportMessage.java
--- TransportMessage.java 14 Nov 2002 05:00:42 -0000 1.19
+++ TransportMessage.java 14 Nov 2002 13:46:08 -0000
@@ -169,7 +169,7 @@
if (contentLength != 0) {
int offset = 0;
int bytesRead = 0;
-
+
// We're done reading when we get all the content OR when the stream
// returns a -1.
while ((contentLength < 0 || offset < contentLength) && (bytesRead >= 0))
{
@@ -258,15 +258,12 @@
// Parse and validate content type.
ContentType cType = null;
if (contentType != null) {
- try {
- // Hack since WebSphere puts ;; instead of just ;
- int pos = contentType.indexOf( ";;" );
- if ( pos != -1 )
- contentType = contentType.substring(0,pos) +
- contentType.substring(pos+1) ;
- cType = new ContentType(contentType);
- } catch(ParseException pe) {
- }
+ // Hack since WebSphere puts ;; instead of just ;
+ int pos = contentType.indexOf( ";;" );
+ if ( pos != -1 )
+ contentType = contentType.substring(0,pos) +
+ contentType.substring(pos+1) ;
+ cType = MimeUtils.getContentType(contentType);
}
if (cType == null)
throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
@@ -321,7 +318,7 @@
// Find root part.
rootPart = ctx.getRootPart();
- rootContentType = new ContentType(rootPart.getContentType());
+ rootContentType = MimeUtils.getContentType(rootPart.getContentType());
ByteArrayDataSource bads = new ByteArrayDataSource(
rootPart.getInputStream(), null);
rootBytes = bads.toByteArray();
@@ -420,7 +417,7 @@
new ByteArrayOutputStream(65536);
ctx.writeTo(payload);
bytes = payload.toByteArray();
-
+
// Now strip off the headers. (Grmbl, get rid of JavaMail
// for MIME support). Just intercept the Content-Type
// header. We don't want any of the MIME headers, and we know the
@@ -514,7 +511,7 @@
MimeBodyPart rootPart = ctx.getRootPart();
if (rootPart != null) {
String ctype = rootPart.getContentType();
- ContentType type = new ContentType(ctype);
+ ContentType type = MimeUtils.getContentType(ctype);
if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
ByteArrayDataSource ds = new ByteArrayDataSource(
rootPart.getInputStream(), ctype);
Index: Constants.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/Constants.java,v
retrieving revision 1.28
diff -u -r1.28 Constants.java
--- Constants.java 14 Nov 2002 05:00:42 -0000 1.28
+++ Constants.java 14 Nov 2002 13:47:35 -0000
@@ -59,6 +59,7 @@
import org.apache.soap.util.xml.QName;
import javax.mail.internet.ContentType;
+import org.apache.soap.util.mime.MimeUtils;
/**
* <em>SOAP</em> constants.
@@ -85,7 +86,7 @@
"http://schemas.xmlsoap.org/soap/envelope/";
public static final String NS_URI_SOAP_ENC =
"http://schemas.xmlsoap.org/soap/encoding/";
-
+
public static final String NS_URI_1999_SCHEMA_XSI =
"http://www.w3.org/1999/XMLSchema-instance";
public static final String NS_URI_1999_SCHEMA_XSD =
@@ -143,7 +144,7 @@
public static final String HEADERVAL_CONTENT_ENCODING = "gzip";
// XML Declaration string
- public static final String XML_DECL =
+ public static final String XML_DECL =
"<?xml version='1.0' encoding='UTF-8'?>\r\n";
// Element names.
@@ -308,9 +309,9 @@
public static final QName object2001QName =
new QName(Constants.NS_URI_2001_SCHEMA_XSD, "anyType");
- public static final ContentType CTYPE_TEXT_ALL = new ContentType("text", "*", null);
- public static final ContentType CTYPE_TEXT_XML = new ContentType("text", "xml",
null);
- public static final ContentType CTYPE_MULTIPART =
- new ContentType(HEADERVAL_CONTENT_TYPE_MULTIPART_PRIMARY, "*", null);
+ public static final ContentType CTYPE_TEXT_ALL = MimeUtils.getContentType("text/*");
+ public static final ContentType CTYPE_TEXT_XML =
+MimeUtils.getContentType("text/xml");
+ public static final ContentType CTYPE_MULTIPART = MimeUtils.getContentType(
+ HEADERVAL_CONTENT_TYPE_MULTIPART_PRIMARY + "/*");
}
Index: SOAPContext.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java,v
retrieving revision 1.13
diff -u -r1.13 SOAPContext.java
--- SOAPContext.java 6 Nov 2002 18:08:04 -0000 1.13
+++ SOAPContext.java 14 Nov 2002 13:51:01 -0000
@@ -476,7 +476,7 @@
public MimeBodyPart getRootPart() throws MessagingException {
MimeBodyPart rootPart = null;
if (getCount() > 1) {
- String startCid = new ContentType(
+ String startCid = MimeUtils.getContentType(
parts.getContentType()).getParameter("start");
if (startCid != null)
rootPart = getBodyPart(MimeUtils.decode(startCid));
Index: MimeUtils.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/util/mime/MimeUtils.java,v
retrieving revision 1.5
diff -u -r1.5 MimeUtils.java
--- MimeUtils.java 6 Sep 2002 17:50:27 -0000 1.5
+++ MimeUtils.java 14 Nov 2002 13:53:19 -0000
@@ -70,6 +70,8 @@
*/
public class MimeUtils {
+
+ private static HashMap contentTypes = new HashMap();
/**
* Get a unique value.
*
@@ -100,11 +102,8 @@
*/
public static String getEncoding(String type, String defaultEncoding) {
String encoding = null;
- try {
if (type != null && !type.equals(""))
- encoding = new ContentType(type).getParameter("charset");
- } catch(ParseException pe) {
- }
+ encoding = getContentType(type).getParameter("charset");
if (encoding == null)
encoding = defaultEncoding;
else
@@ -135,5 +134,24 @@
}
}
return ret.toString();
+ }
+
+ /**
+ * Return a content type from shared pool
+ */
+ public static ContentType getContentType(String ctype) {
+ synchronized (contentTypes) {
+ ContentType type = (ContentType)contentTypes.get(ctype);
+ if (type == null) {
+ try {
+ type = new ContentType(ctype);
+ }
+ catch (ParseException e) {
+ return null;
+ }
+ contentTypes.put(ctype, type);
+ }
+ return type;
+ }
}
}
Index: Call.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/rpc/Call.java,v
retrieving revision 1.20
diff -u -r1.20 Call.java
--- Call.java 12 Nov 2002 14:34:56 -0000 1.20
+++ Call.java 14 Nov 2002 13:58:00 -0000
@@ -66,6 +66,7 @@
import org.xml.sax.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.util.IOUtils;
+import org.apache.soap.util.mime.MimeUtils;
import org.apache.soap.*;
import org.apache.soap.encoding.*;
import org.apache.soap.transport.*;
@@ -273,10 +274,7 @@
MimeBodyPart rootPart = respCtx.getRootPart();
String ctype = rootPart.getContentType();
ContentType type = null;
- try {
- type = new ContentType(ctype);
- }
- catch (ParseException e) {}
+ type = MimeUtils.getContentType(ctype);
if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
// Get the input stream to read the response envelope from.
-- To unsubscribe, e-mail: <mailto:soap-dev-unsubscribe@;xml.apache.org> For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org>
