We are seeing excessive CPU burn (top > 300% on multicore machine) in
multiple versions of Tomcat that use APR connectors exclusively.  The
problem does not correlate with load.  We initially saw it on 6.0.35
and subsequently on 7.0.23 as we attempted to upgrade around the
problem.  We have determined that the component common to both
versions is tomcat-native 1.1.22.  (We were not seeing this behavior
on our previous component mix of 6.0.26/1.1.20.)

In addition to the circumstantial evidence of version changes, we have
some JVM data that implicate tomcat-native.  We've taken thread dumps
and YourKit snapshots (w/CPU sampling enabled) during the problem
periods and a consistent pattern appears: at least two connector
threads are in org.apache.tomcat.jni.Socket.sendbb(long, int, int)
throughout the period of CPU churn.  The following instrumented thread
dump of active threads is illustrative of this pattern:

Stacks at 10:57:51 AM (uptime 5:13:38)

catalina-exec-1 [WAITING] CPU time: 2:03
sun.misc.Unsafe.park(boolean, long)
java.util.concurrent.locks.LockSupport.parkNanos(Object, long)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(long)
java.util.concurrent.LinkedBlockingQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
java.util.concurrent.ThreadPoolExecutor.getTask()
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

catalina-exec-10 [RUNNABLE, IN_NATIVE] CPU time: 2:28
org.apache.tomcat.jni.Socket.sendbb(long, int, int)
org.apache.coyote.http11.InternalAprOutputBuffer.flushBuffer()
org.apache.coyote.http11.InternalAprOutputBuffer.access$100(InternalAprOutputBuffer)
org.apache.coyote.http11.InternalAprOutputBuffer$SocketOutputBuffer.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.AbstractOutputBuffer.doWrite(ByteChunk, Response)
org.apache.coyote.Response.doWrite(ByteChunk)
org.apache.catalina.connector.OutputBuffer.realWriteBytes(byte[], int, int)
org.apache.tomcat.util.buf.ByteChunk.append(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.writeBytes(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.write(byte[], int, int)
org.apache.catalina.connector.CoyoteOutputStream.write(byte[], int, int)
org.apache.catalina.servlets.DefaultServlet.copy(CacheEntry,
InputStream, ServletOutputStream)
org.apache.catalina.servlets.DefaultServlet.serveResource(HttpServletRequest,
HttpServletResponse, boolean)
org.apache.catalina.servlets.DefaultServlet.doGet(HttpServletRequest,
HttpServletResponse)
javax.servlet.http.HttpServlet.service(HttpServletRequest, HttpServletResponse)
javax.servlet.http.HttpServlet.service(ServletRequest, ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.RequestDumperFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
com.github.inspektr.common.web.ClientInfoThreadLocalFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.CharacterEncodingFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.StandardWrapperValve.invoke(Request, Response)
org.apache.catalina.core.StandardContextValve.invoke(Request, Response)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(Request, Response)
org.apache.catalina.core.StandardHostValve.invoke(Request, Response)
org.apache.catalina.valves.ErrorReportValve.invoke(Request, Response)
org.apache.catalina.valves.AccessLogValve.invoke(Request, Response)
org.apache.catalina.core.StandardEngineValve.invoke(Request, Response)
org.apache.catalina.connector.CoyoteAdapter.service(Request, Response)
org.apache.coyote.http11.AbstractHttp11Processor.process(SocketWrapper)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(SocketWrapper,
SocketStatus)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run()
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Runnable)
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

catalina-exec-11 [RUNNABLE, IN_NATIVE] CPU time: 10:19
org.apache.tomcat.jni.Socket.sendbb(long, int, int)
org.apache.coyote.http11.InternalAprOutputBuffer.flushBuffer()
org.apache.coyote.http11.InternalAprOutputBuffer.access$100(InternalAprOutputBuffer)
org.apache.coyote.http11.InternalAprOutputBuffer$SocketOutputBuffer.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.AbstractOutputBuffer.doWrite(ByteChunk, Response)
org.apache.coyote.Response.doWrite(ByteChunk)
org.apache.catalina.connector.OutputBuffer.realWriteBytes(byte[], int, int)
org.apache.tomcat.util.buf.ByteChunk.append(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.writeBytes(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.write(byte[], int, int)
org.apache.catalina.connector.CoyoteOutputStream.write(byte[], int, int)
org.apache.catalina.servlets.DefaultServlet.copy(CacheEntry,
InputStream, ServletOutputStream)
org.apache.catalina.servlets.DefaultServlet.serveResource(HttpServletRequest,
HttpServletResponse, boolean)
org.apache.catalina.servlets.DefaultServlet.doGet(HttpServletRequest,
HttpServletResponse)
javax.servlet.http.HttpServlet.service(HttpServletRequest, HttpServletResponse)
javax.servlet.http.HttpServlet.service(ServletRequest, ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.RequestDumperFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
com.github.inspektr.common.web.ClientInfoThreadLocalFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.CharacterEncodingFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.StandardWrapperValve.invoke(Request, Response)
org.apache.catalina.core.StandardContextValve.invoke(Request, Response)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(Request, Response)
org.apache.catalina.core.StandardHostValve.invoke(Request, Response)
org.apache.catalina.valves.ErrorReportValve.invoke(Request, Response)
org.apache.catalina.valves.AccessLogValve.invoke(Request, Response)
org.apache.catalina.core.StandardEngineValve.invoke(Request, Response)
org.apache.catalina.connector.CoyoteAdapter.service(Request, Response)
org.apache.coyote.http11.AbstractHttp11Processor.process(SocketWrapper)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(SocketWrapper,
SocketStatus)
org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run()
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Runnable)
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

catalina-exec-12 [WAITING] CPU time: 1:39
sun.misc.Unsafe.park(boolean, long)
java.util.concurrent.locks.LockSupport.parkNanos(Object, long)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(long)
java.util.concurrent.LinkedBlockingQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
java.util.concurrent.ThreadPoolExecutor.getTask()
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

catalina-exec-3 [WAITING] CPU time: 2:26
sun.misc.Unsafe.park(boolean, long)
java.util.concurrent.locks.LockSupport.parkNanos(Object, long)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(long)
java.util.concurrent.LinkedBlockingQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
org.apache.tomcat.util.threads.TaskQueue.poll(long, TimeUnit)
java.util.concurrent.ThreadPoolExecutor.getTask()
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

catalina-exec-5 [RUNNABLE, IN_NATIVE] CPU time: 3:00
org.apache.tomcat.jni.Socket.sendbb(long, int, int)
org.apache.coyote.http11.InternalAprOutputBuffer.flushBuffer()
org.apache.coyote.http11.InternalAprOutputBuffer.access$100(InternalAprOutputBuffer)
org.apache.coyote.http11.InternalAprOutputBuffer$SocketOutputBuffer.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(ByteChunk,
Response)
org.apache.coyote.http11.AbstractOutputBuffer.doWrite(ByteChunk, Response)
org.apache.coyote.Response.doWrite(ByteChunk)
org.apache.catalina.connector.OutputBuffer.realWriteBytes(byte[], int, int)
org.apache.tomcat.util.buf.ByteChunk.flushBuffer()
org.apache.tomcat.util.buf.ByteChunk.append(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.writeBytes(byte[], int, int)
org.apache.catalina.connector.OutputBuffer.write(byte[], int, int)
org.apache.catalina.connector.CoyoteOutputStream.write(byte[], int, int)
org.apache.catalina.servlets.DefaultServlet.copyRange(InputStream,
ServletOutputStream, long, long)
org.apache.catalina.servlets.DefaultServlet.copy(CacheEntry,
ServletOutputStream, DefaultServlet$Range)
org.apache.catalina.servlets.DefaultServlet.serveResource(HttpServletRequest,
HttpServletResponse, boolean)
org.apache.catalina.servlets.DefaultServlet.doGet(HttpServletRequest,
HttpServletResponse)
javax.servlet.http.HttpServlet.service(HttpServletRequest, HttpServletResponse)
javax.servlet.http.HttpServlet.service(ServletRequest, ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.RequestDumperFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
com.github.inspektr.common.web.ClientInfoThreadLocalFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
edu.vt.middleware.servlet.filter.CharacterEncodingFilter.doFilter(ServletRequest,
ServletResponse, FilterChain)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest,
ServletResponse)
org.apache.catalina.core.StandardWrapperValve.invoke(Request, Response)
org.apache.catalina.core.StandardContextValve.invoke(Request, Response)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(Request, Response)
org.apache.catalina.core.StandardHostValve.invoke(Request, Response)
org.apache.catalina.valves.ErrorReportValve.invoke(Request, Response)
org.apache.catalina.valves.AccessLogValve.invoke(Request, Response)
org.apache.catalina.core.StandardEngineValve.invoke(Request, Response)
org.apache.catalina.connector.CoyoteAdapter.service(Request, Response)
org.apache.coyote.http11.AbstractHttp11Processor.process(SocketWrapper)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(SocketWrapper,
SocketStatus)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run()
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Runnable)
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

ContainerBackgroundProcessor[StandardEngine[Catalina]] [RUNNABLE,
IN_NATIVE] CPU time: 23:33
org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery()
org.apache.catalina.session.JDBCStore.load(String)
org.apache.catalina.session.StoreBase.processExpires()
org.apache.catalina.session.PersistentManagerBase.processExpires()
org.apache.catalina.session.ManagerBase.backgroundProcess()
org.apache.catalina.core.ContainerBase.backgroundProcess()
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader)
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader)
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader)
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run()
java.lang.Thread.run()

pool-10-thread-1 [WAITING] CPU time: 4:11
sun.misc.Unsafe.park(boolean, long)
java.util.concurrent.locks.LockSupport.park(Object)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()
java.util.concurrent.LinkedBlockingQueue.take()
java.util.concurrent.ThreadPoolExecutor.getTask()
java.util.concurrent.ThreadPoolExecutor$Worker.run()
java.lang.Thread.run()

Shown threads: 8 of 164

Graphs of CPU usage over time show a sharp increase when a second
thread enters sendbb; conversely there is a sharp decrease as soon as
all but a single thread drop out of the method.  Additionally, there
may be a correlation with CPU usage and the number of threads in
sendbb; for example, the CPU burn may be greater when three threads
are in sendbb versus two.

This feels like a concurrency bug: hard to reproduce, sporadic, and
correlates with number of threads acting on the same code path.
Please let me know if you'd like me to do anything further that may
help determine whether this is, in fact, a bug.  I'm happy to create a
bug report if needed.

M

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to