You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/12/16 21:39:19 UTC

svn commit: r1551340 - in /tomcat/trunk/java/org/apache/tomcat/util: net/AbstractEndpoint.java net/AprEndpoint.java net/JIoEndpoint.java net/NioEndpoint.java threads/TaskThreadFactory.java

Author: markt
Date: Mon Dec 16 20:39:19 2013
New Revision: 1551340

URL: http://svn.apache.org/r1551340
Log:
Performance improvement
The context class loader was set in *Endpoint#processSocket() in case a new thread was created since this method may be triggered from web application code and that in turn would trigger a memory leak since the thread would end up with the web app class loader as its context class loader. However, this is only an issue when creating threads and since getting the current class loader is expensive, move this code to where threads are created rather than calling it on every call to *Endpoint#processSocket().
This appears (on my fairly unscientific tests) to remove ~5% of the overhead from all request processing.

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Mon Dec 16 20:39:19 2013
@@ -20,7 +20,6 @@ import java.io.File;
 import java.io.OutputStreamWriter;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -97,22 +96,6 @@ public abstract class AbstractEndpoint<S
     }
 
 
-    protected static class PrivilegedSetTccl implements PrivilegedAction<Void> {
-
-        private ClassLoader cl;
-
-        PrivilegedSetTccl(ClassLoader cl) {
-            this.cl = cl;
-        }
-
-        @Override
-        public Void run() {
-            Thread.currentThread().setContextClassLoader(cl);
-            return null;
-        }
-    }
-
-
     private static final int INITIAL_ERROR_DELAY = 50;
     private static final int MAX_ERROR_DELAY = 1600;
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Mon Dec 16 20:39:19 2013
@@ -17,8 +17,6 @@
 
 package org.apache.tomcat.util.net;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -892,26 +890,7 @@ public class AprEndpoint extends Abstrac
                     SocketProcessor proc = new SocketProcessor(socket, status);
                     Executor executor = getExecutor();
                     if (dispatch && executor != null) {
-                        ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                        try {
-                            //threads should not be created by the webapp classloader
-                            if (Constants.IS_SECURITY_ENABLED) {
-                                PrivilegedAction<Void> pa = new PrivilegedSetTccl(
-                                        getClass().getClassLoader());
-                                AccessController.doPrivileged(pa);
-                            } else {
-                                Thread.currentThread().setContextClassLoader(
-                                        getClass().getClassLoader());
-                            }
-                            executor.execute(proc);
-                        } finally {
-                            if (Constants.IS_SECURITY_ENABLED) {
-                                PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader);
-                                AccessController.doPrivileged(pa);
-                            } else {
-                                Thread.currentThread().setContextClassLoader(loader);
-                            }
-                        }
+                        executor.execute(proc);
                     } else {
                         proc.run();
                     }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Mon Dec 16 20:39:19 2013
@@ -22,8 +22,6 @@ import java.net.BindException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
@@ -566,31 +564,11 @@ public class JIoEndpoint extends Abstrac
                     SocketProcessor proc = new SocketProcessor(socket,status);
                     Executor executor = getExecutor();
                     if (dispatch && executor != null) {
-                        ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                        try {
-                            //threads should not be created by the webapp classloader
-                            if (Constants.IS_SECURITY_ENABLED) {
-                                PrivilegedAction<Void> pa =
-                                        new PrivilegedSetTccl(
-                                        getClass().getClassLoader());
-                                AccessController.doPrivileged(pa);
-                            } else {
-                                Thread.currentThread().setContextClassLoader(
-                                        getClass().getClassLoader());
-                            }
-                            // During shutdown, executor may be null - avoid NPE
-                            if (!running) {
-                                return;
-                            }
-                            getExecutor().execute(proc);
-                        } finally {
-                            if (Constants.IS_SECURITY_ENABLED) {
-                                PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader);
-                                AccessController.doPrivileged(pa);
-                            } else {
-                                Thread.currentThread().setContextClassLoader(loader);
-                            }
+                        // During shutdown, executor may be null - avoid NPE
+                        if (!running) {
+                            return;
                         }
+                        getExecutor().execute(proc);
                     } else {
                         proc.run();
                     }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Mon Dec 16 20:39:19 2013
@@ -32,8 +32,6 @@ import java.nio.channels.Selector;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.WritableByteChannel;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
@@ -631,26 +629,7 @@ public class NioEndpoint extends Abstrac
             else sc.reset(socket,status);
             Executor executor = getExecutor();
             if (dispatch && executor != null) {
-                ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                try {
-                    //threads should not be created by the webapp classloader
-                    if (Constants.IS_SECURITY_ENABLED) {
-                        PrivilegedAction<Void> pa = new PrivilegedSetTccl(
-                                getClass().getClassLoader());
-                        AccessController.doPrivileged(pa);
-                    } else {
-                        Thread.currentThread().setContextClassLoader(
-                                getClass().getClassLoader());
-                    }
-                    executor.execute(sc);
-                } finally {
-                    if (Constants.IS_SECURITY_ENABLED) {
-                        PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader);
-                        AccessController.doPrivileged(pa);
-                    } else {
-                        Thread.currentThread().setContextClassLoader(loader);
-                    }
-                }
+                executor.execute(sc);
             } else {
                 sc.run();
             }
@@ -872,7 +851,7 @@ public class NioEndpoint extends Abstrac
         private volatile boolean close = false;
         private long nextExpiration = 0;//optimize expiration handling
 
-        private AtomicLong wakeupCounter = new AtomicLong(0l);
+        private AtomicLong wakeupCounter = new AtomicLong(0);
 
         private volatile int keyCount = 0;
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java?rev=1551340&r1=1551339&r2=1551340&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java Mon Dec 16 20:39:19 2013
@@ -16,19 +16,24 @@
  */
 package org.apache.tomcat.util.threads;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.util.net.Constants;
 /**
- * Simple task thread factory to use to create threads for an executor implementation.
- * @author fhanik
- *
+ * Simple task thread factory to use to create threads for an executor
+ * implementation.
  */
 public class TaskThreadFactory implements ThreadFactory {
+
     private final ThreadGroup group;
     private final AtomicInteger threadNumber = new AtomicInteger(1);
     private final String namePrefix;
     private final boolean daemon;
     private final int threadPriority;
+
     public TaskThreadFactory(String namePrefix, boolean daemon, int priority) {
         SecurityManager s = System.getSecurityManager();
         group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
@@ -39,10 +44,44 @@ public class TaskThreadFactory implement
 
     @Override
     public Thread newThread(Runnable r) {
-        TaskThread t = new TaskThread(group, r, namePrefix + threadNumber.getAndIncrement());
-        t.setDaemon(daemon);
-        t.setPriority(threadPriority);
-        return t;
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        try {
+            // Threads should not be created by the webapp classloader
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedAction<Void> pa = new PrivilegedSetTccl(
+                        getClass().getClassLoader());
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(
+                        getClass().getClassLoader());
+            }
+            TaskThread t = new TaskThread(group, r, namePrefix + threadNumber.getAndIncrement());
+            t.setDaemon(daemon);
+            t.setPriority(threadPriority);
+            return t;
+        } finally {
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader);
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(loader);
+            }
+        }
     }
 
+
+    private static class PrivilegedSetTccl implements PrivilegedAction<Void> {
+
+        private ClassLoader cl;
+
+        PrivilegedSetTccl(ClassLoader cl) {
+            this.cl = cl;
+        }
+
+        @Override
+        public Void run() {
+            Thread.currentThread().setContextClassLoader(cl);
+            return null;
+        }
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org