You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "Sebastien Bocq (JIRA)" <ax...@ws.apache.org> on 2004/12/07 10:33:19 UTC

[jira] Created: (AXIS-1701) axis performance in multithreading env

axis performance in multithreading env
--------------------------------------

         Key: AXIS-1701
         URL: http://nagoya.apache.org/jira/browse/AXIS-1701
     Project: Axis
        Type: Bug
  Components: Serialization/Deserialization  
    Versions: 1.2RC2    
 Environment: W2K, java full version "1.4.2_01-b06"
    Reporter: Sebastien Bocq


Hi,

While doing performance tests on deserialization, I noticed that Axis 
scales very poorly when increasing the number of threads.

Here are the figures:
5 threads, 1000 messages: 15 seconds
10 threads, 1000 messages: 56 seconds
15 threads, 1000 messages: 93 seconds

The root of the problem is in XMLUtils. Each time a node is created via 
the static fuction newDocument(...), there are two functions, 
getDocumentBuilder() and realeaseDocumentBuilder(), called which both 
peform synchronisation over a pool of document builders 
(documentBuilders ). Since XML documents contain many nodes and there 
are at least two synchronization points in the code per node created, I 
let you imagine the overhead suffered when more threads come into play.

I was able to achieve a significant performance boost by replacing the 
pool of DocumentBuilders (documentBuilders) by a single document builder 
stored in a ThreadLocal variable. This was already suggested a while ago 
in this mailing list (see "Performance Issues with AXIS & Axis Response 
time appears linear with load").

The results of my benchmark with the changes brought to the code are 
shown below.

5 threads, 1000 messages:  13seconds
10 threads, 1000 messages:  25,5 seconds
15 threads, 1000 messages: 37 seconds

As you can see, deserialization time scales now linearly with the number 
of threads which is a lot better. I placed a patch below. Could 
you include sth equivalent in the next release of the Axis.

Thanks,
Sebastien

--- XMLUtilsOld.java	Tue Nov 16 19:04:44 2004
+++ XMLUtilsNew.java	Tue Dec  7 10:03:59 2004
@@ -80,8 +80,23 @@
     private static final String saxParserFactoryProperty =
         "javax.xml.parsers.SAXParserFactory";
 
-    private static DocumentBuilderFactory dbf = getDOMFactory();
-    private static Stack                  documentBuilders = new Stack(); 
+    // DocumentBuilderFactory is not thread-safe. Place DocumentBuilder 
+    // in thread local variable to remove synchronization overhead.
+    
+    // private static DocumentBuilderFactory dbf = getDOMFactory();
+    // private static Stack                  documentBuilders = new Stack(); 
+    private static class ThreadLocalDocumentBuilder extends ThreadLocal {
+    	protected Object initialValue() {
+    		try {
+				return getDOMFactory().newDocumentBuilder();
+			} catch (ParserConfigurationException e) {
+	            log.error(Messages.getMessage("parserConfigurationException00"), e);
+			}
+			return null;
+    	}
+    }
+    private static ThreadLocalDocumentBuilder documentBuilder = new ThreadLocalDocumentBuilder();
+    
     private static SAXParserFactory       saxFactory;
     private static Stack                  saxParsers = new Stack();
     private static DefaultHandler doNothingContentHandler = new DefaultHandler();
@@ -206,36 +221,6 @@
         }
         return( dbf );
     }
-
-    /**
-     * Gets a DocumentBuilder
-     * @return DocumentBuilder
-     * @throws ParserConfigurationException
-     */ 
-    public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
-        synchronized (documentBuilders) {
-            if (!documentBuilders.empty()) {
-                return (DocumentBuilder) documentBuilders.pop();
-            }
-        }
-        DocumentBuilder db = null;
-        synchronized (dbf) {
-            db = dbf.newDocumentBuilder();
-        }
-        return db;
-    }
-
-    /**
-     * Releases a DocumentBuilder
-     * @param db
-     */ 
-    public static void releaseDocumentBuilder(DocumentBuilder db) {
-        synchronized (documentBuilders) {
-            db.setErrorHandler(null); // setting implementation default
-            db.setEntityResolver(null); // setting implementation default
-            documentBuilders.push(db);
-        }
-    }
     
     private static boolean tryReset= true;
 
@@ -302,16 +287,9 @@
      */
     public static Document newDocument()
             throws ParserConfigurationException {
-        DocumentBuilder db = null;
-        try {
-            db = getDocumentBuilder();
-            Document doc = db.newDocument();
-            return doc;
-        } finally {
-            if (db != null) {
-                releaseDocumentBuilder(db);
-            }
-        }
+        DocumentBuilder db = (DocumentBuilder) documentBuilder.get();
+        Document doc = db.newDocument();
+        return doc;
     }
 
     /**
@@ -324,18 +302,11 @@
     public static Document newDocument(InputSource inp)
         throws ParserConfigurationException, SAXException, IOException
     {
-        DocumentBuilder db = null;
-        try {
-            db = getDocumentBuilder();
-            db.setEntityResolver(new DefaultEntityResolver());
-            db.setErrorHandler(new ParserErrorHandler());
-            Document doc = db.parse(inp);
-            return doc;
-        } finally {
-            if (db != null) {
-                releaseDocumentBuilder(db);
-            }
-        }
+        DocumentBuilder db = (DocumentBuilder) documentBuilder.get();
+        db.setEntityResolver(new DefaultEntityResolver());
+        db.setErrorHandler(new ParserErrorHandler());
+        Document doc = db.parse(inp);
+        return doc;
     }
 
     /**


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://nagoya.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


[jira] Resolved: (AXIS-1701) axis performance in multithreading env

Posted by "Davanum Srinivas (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-1701?page=all ]
     
Davanum Srinivas resolved AXIS-1701:
------------------------------------

    Resolution: Fixed

this has been fixed. please try latest CVS / Nightly.

thanks,
dims

> axis performance in multithreading env
> --------------------------------------
>
>          Key: AXIS-1701
>          URL: http://issues.apache.org/jira/browse/AXIS-1701
>      Project: Axis
>         Type: Bug
>   Components: Serialization/Deserialization
>     Versions: 1.2RC2
>  Environment: W2K, java full version "1.4.2_01-b06"
>     Reporter: Sebastien Bocq

>
> Hi,
> While doing performance tests on deserialization, I noticed that Axis 
> scales very poorly when increasing the number of threads.
> Here are the figures:
> 5 threads, 1000 messages: 15 seconds
> 10 threads, 1000 messages: 56 seconds
> 15 threads, 1000 messages: 93 seconds
> The root of the problem is in XMLUtils. Each time a node is created via 
> the static fuction newDocument(...), there are two functions, 
> getDocumentBuilder() and realeaseDocumentBuilder(), called which both 
> peform synchronisation over a pool of document builders 
> (documentBuilders ). Since XML documents contain many nodes and there 
> are at least two synchronization points in the code per node created, I 
> let you imagine the overhead suffered when more threads come into play.
> I was able to achieve a significant performance boost by replacing the 
> pool of DocumentBuilders (documentBuilders) by a single document builder 
> stored in a ThreadLocal variable. This was already suggested a while ago 
> in this mailing list (see "Performance Issues with AXIS & Axis Response 
> time appears linear with load").
> The results of my benchmark with the changes brought to the code are 
> shown below.
> 5 threads, 1000 messages:  13seconds
> 10 threads, 1000 messages:  25,5 seconds
> 15 threads, 1000 messages: 37 seconds
> As you can see, deserialization time scales now linearly with the number 
> of threads which is a lot better. I placed a patch below. Could 
> you include sth equivalent in the next release of the Axis.
> Thanks,
> Sebastien
> --- XMLUtilsOld.java	Tue Nov 16 19:04:44 2004
> +++ XMLUtilsNew.java	Tue Dec  7 10:03:59 2004
> @@ -80,8 +80,23 @@
>      private static final String saxParserFactoryProperty =
>          "javax.xml.parsers.SAXParserFactory";
>  
> -    private static DocumentBuilderFactory dbf = getDOMFactory();
> -    private static Stack                  documentBuilders = new Stack(); 
> +    // DocumentBuilderFactory is not thread-safe. Place DocumentBuilder 
> +    // in thread local variable to remove synchronization overhead.
> +    
> +    // private static DocumentBuilderFactory dbf = getDOMFactory();
> +    // private static Stack                  documentBuilders = new Stack(); 
> +    private static class ThreadLocalDocumentBuilder extends ThreadLocal {
> +    	protected Object initialValue() {
> +    		try {
> +				return getDOMFactory().newDocumentBuilder();
> +			} catch (ParserConfigurationException e) {
> +	            log.error(Messages.getMessage("parserConfigurationException00"), e);
> +			}
> +			return null;
> +    	}
> +    }
> +    private static ThreadLocalDocumentBuilder documentBuilder = new ThreadLocalDocumentBuilder();
> +    
>      private static SAXParserFactory       saxFactory;
>      private static Stack                  saxParsers = new Stack();
>      private static DefaultHandler doNothingContentHandler = new DefaultHandler();
> @@ -206,36 +221,6 @@
>          }
>          return( dbf );
>      }
> -
> -    /**
> -     * Gets a DocumentBuilder
> -     * @return DocumentBuilder
> -     * @throws ParserConfigurationException
> -     */ 
> -    public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
> -        synchronized (documentBuilders) {
> -            if (!documentBuilders.empty()) {
> -                return (DocumentBuilder) documentBuilders.pop();
> -            }
> -        }
> -        DocumentBuilder db = null;
> -        synchronized (dbf) {
> -            db = dbf.newDocumentBuilder();
> -        }
> -        return db;
> -    }
> -
> -    /**
> -     * Releases a DocumentBuilder
> -     * @param db
> -     */ 
> -    public static void releaseDocumentBuilder(DocumentBuilder db) {
> -        synchronized (documentBuilders) {
> -            db.setErrorHandler(null); // setting implementation default
> -            db.setEntityResolver(null); // setting implementation default
> -            documentBuilders.push(db);
> -        }
> -    }
>      
>      private static boolean tryReset= true;
>  
> @@ -302,16 +287,9 @@
>       */
>      public static Document newDocument()
>              throws ParserConfigurationException {
> -        DocumentBuilder db = null;
> -        try {
> -            db = getDocumentBuilder();
> -            Document doc = db.newDocument();
> -            return doc;
> -        } finally {
> -            if (db != null) {
> -                releaseDocumentBuilder(db);
> -            }
> -        }
> +        DocumentBuilder db = (DocumentBuilder) documentBuilder.get();
> +        Document doc = db.newDocument();
> +        return doc;
>      }
>  
>      /**
> @@ -324,18 +302,11 @@
>      public static Document newDocument(InputSource inp)
>          throws ParserConfigurationException, SAXException, IOException
>      {
> -        DocumentBuilder db = null;
> -        try {
> -            db = getDocumentBuilder();
> -            db.setEntityResolver(new DefaultEntityResolver());
> -            db.setErrorHandler(new ParserErrorHandler());
> -            Document doc = db.parse(inp);
> -            return doc;
> -        } finally {
> -            if (db != null) {
> -                releaseDocumentBuilder(db);
> -            }
> -        }
> +        DocumentBuilder db = (DocumentBuilder) documentBuilder.get();
> +        db.setEntityResolver(new DefaultEntityResolver());
> +        db.setErrorHandler(new ParserErrorHandler());
> +        Document doc = db.parse(inp);
> +        return doc;
>      }
>  
>      /**

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira