Author: markt Date: Mon Dec 16 21:05:03 2013 New Revision: 1551356 URL: http://svn.apache.org/r1551356 Log: Performance improvement Partial fix for https://issues.apache.org/bugzilla/show_bug.cgi?id=55855 Make the adding of the WsFilter lazy so it doesn't get added to web apps that don't need it.
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1551352 Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java?rev=1551356&r1=1551355&r2=1551356&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java Mon Dec 16 21:05:03 2013 @@ -87,74 +87,89 @@ public class WsServerContainer extends W private volatile boolean addAllowed = true; private final ConcurrentHashMap<String,Set<WsSession>> authenticatedSessions = new ConcurrentHashMap<String, Set<WsSession>>(); - private final ExecutorService executorService; + private ExecutorService executorService; + private volatile boolean initialized = false; WsServerContainer(ServletContext servletContext) { - this.servletContext = servletContext; + } - // Configure servlet context wide defaults - String value = servletContext.getInitParameter( - Constants.BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM); - if (value != null) { - setDefaultMaxBinaryMessageBufferSize(Integer.parseInt(value)); - } - - value = servletContext.getInitParameter( - Constants.TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM); - if (value != null) { - setDefaultMaxTextMessageBufferSize(Integer.parseInt(value)); - } - - value = servletContext.getInitParameter( - Constants.ENFORCE_NO_ADD_AFTER_HANDSHAKE_CONTEXT_INIT_PARAM); - if (value != null) { - setEnforceNoAddAfterHandshake(Boolean.parseBoolean(value)); - } - // Executor config - int executorCoreSize = 0; - int executorMaxSize = 10; - long executorKeepAliveTimeSeconds = 60; - value = servletContext.getInitParameter( - Constants.EXECUTOR_CORE_SIZE_INIT_PARAM); - if (value != null) { - executorCoreSize = Integer.parseInt(value); - } - value = servletContext.getInitParameter( - Constants.EXECUTOR_MAX_SIZE_INIT_PARAM); - if (value != null) { - executorMaxSize = Integer.parseInt(value); - } - value = servletContext.getInitParameter( - Constants.EXECUTOR_KEEPALIVETIME_SECONDS_INIT_PARAM); - if (value != null) { - executorKeepAliveTimeSeconds = Long.parseLong(value); - } - - FilterRegistration.Dynamic fr = servletContext.addFilter( - WsFilter.class.getName(), new WsFilter()); - fr.setAsyncSupported(true); - - EnumSet<DispatcherType> types = EnumSet.of(DispatcherType.REQUEST, - DispatcherType.FORWARD); - - fr.addMappingForUrlPatterns(types, true, "/*"); - - // Use a per web application executor for any threads the the WebSocket - // server code needs to create. Group all of the threads under a single - // ThreadGroup. - StringBuffer threadGroupName = new StringBuffer("WebSocketServer-"); - if ("".equals(servletContext.getContextPath())) { - threadGroupName.append("ROOT"); - } else { - threadGroupName.append(servletContext.getContextPath()); - } - ThreadGroup threadGroup = new ThreadGroup(threadGroupName.toString()); - WsThreadFactory wsThreadFactory = new WsThreadFactory(threadGroup); + private void init() { + + // Double checked locking. This is safe since Java > 1.5 and initialized + // is volatile + if (initialized) { + return; + } + synchronized (this) { + if (initialized) { + return; + } + initialized = true; + + // Configure servlet context wide defaults + String value = servletContext.getInitParameter( + Constants.BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM); + if (value != null) { + setDefaultMaxBinaryMessageBufferSize(Integer.parseInt(value)); + } + + value = servletContext.getInitParameter( + Constants.TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM); + if (value != null) { + setDefaultMaxTextMessageBufferSize(Integer.parseInt(value)); + } - executorService = new ThreadPoolExecutor(executorCoreSize, - executorMaxSize, executorKeepAliveTimeSeconds, TimeUnit.SECONDS, - new LinkedBlockingQueue<Runnable>(), wsThreadFactory); + value = servletContext.getInitParameter( + Constants.ENFORCE_NO_ADD_AFTER_HANDSHAKE_CONTEXT_INIT_PARAM); + if (value != null) { + setEnforceNoAddAfterHandshake(Boolean.parseBoolean(value)); + } + // Executor config + int executorCoreSize = 0; + int executorMaxSize = 10; + long executorKeepAliveTimeSeconds = 60; + value = servletContext.getInitParameter( + Constants.EXECUTOR_CORE_SIZE_INIT_PARAM); + if (value != null) { + executorCoreSize = Integer.parseInt(value); + } + value = servletContext.getInitParameter( + Constants.EXECUTOR_MAX_SIZE_INIT_PARAM); + if (value != null) { + executorMaxSize = Integer.parseInt(value); + } + value = servletContext.getInitParameter( + Constants.EXECUTOR_KEEPALIVETIME_SECONDS_INIT_PARAM); + if (value != null) { + executorKeepAliveTimeSeconds = Long.parseLong(value); + } + + FilterRegistration.Dynamic fr = servletContext.addFilter( + "Tomcat WebSocket (JSR356) Filter", new WsFilter()); + fr.setAsyncSupported(true); + + EnumSet<DispatcherType> types = EnumSet.of(DispatcherType.REQUEST, + DispatcherType.FORWARD); + + fr.addMappingForUrlPatterns(types, true, "/*"); + + // Use a per web application executor for any threads the the WebSocket + // server code needs to create. Group all of the threads under a single + // ThreadGroup. + StringBuffer threadGroupName = new StringBuffer("WebSocketServer-"); + if ("".equals(servletContext.getContextPath())) { + threadGroupName.append("ROOT"); + } else { + threadGroupName.append(servletContext.getContextPath()); + } + ThreadGroup threadGroup = new ThreadGroup(threadGroupName.toString()); + WsThreadFactory wsThreadFactory = new WsThreadFactory(threadGroup); + + executorService = new ThreadPoolExecutor(executorCoreSize, + executorMaxSize, executorKeepAliveTimeSeconds, TimeUnit.SECONDS, + new LinkedBlockingQueue<Runnable>(), wsThreadFactory); + } } @@ -170,6 +185,8 @@ public class WsServerContainer extends W public void addEndpoint(ServerEndpointConfig sec) throws DeploymentException { + init(); + if (enforceNoAddAfterHandshake && !addAllowed) { throw new DeploymentException( sm.getString("serverContainer.addNotAllowed")); @@ -221,6 +238,8 @@ public class WsServerContainer extends W @Override public void addEndpoint(Class<?> pojo) throws DeploymentException { + init(); + ServerEndpoint annotation = pojo.getAnnotation(ServerEndpoint.class); if (annotation == null) { throw new DeploymentException( Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1551356&r1=1551355&r2=1551356&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Mon Dec 16 21:05:03 2013 @@ -76,6 +76,11 @@ Handle the case where a WebSocket annotation configures a message size limit larger than the default permitted by Tomcat. (markt) </fix> + <fix> + <bug>55855</bug>: This is a partial fix that makes the additional of the + WebSocket Filter lazy so that it is not added to web applications that + do not need it. (markt) + </fix> </changelog> </subsection> <subsection name="Cluster"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org