Hi all,

I am currently stress testing my application that uses MINA. In my stress
test I am quite satisfied with the TPS handled by the application, but
still i think there is room for improvement.
I am using mina 2.0.7 and i monitored during the stress test using the
VisualVM. CPU sampler shows  huge amount spend in the
DefaultWriteRequestQueue.size method.

org.apache.mina.core.session.DefaultIoSessionDataStructureFactory$DefaultWriteRequestQueue.size()
70.299576 2138327 ms (70.3%) 2138327 ms

>From the thread dump I could see that most threads were spending most of
the time in the following stack trace:

   java.lang.Thread.State: RUNNABLE
at
java.util.concurrent.ConcurrentLinkedQueue.size(ConcurrentLinkedQueue.java:449)
at
org.apache.mina.core.session.DefaultIoSessionDataStructureFactory$DefaultWriteRequestQueue.size(DefaultIoSessionDataStructureFactory.java:232)
at
org.apache.mina.core.session.AbstractIoSession$CloseAwareWriteQueue.size(AbstractIoSession.java:1388)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$HeadFilter.filterWrite(DefaultIoFilterChain.java:600)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callPreviousFilterWrite(DefaultIoFilterChain.java:482)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1400(DefaultIoFilterChain.java:47)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.filterWrite(DefaultIoFilterChain.java:775)
at
org.apache.mina.core.filterchain.IoFilterAdapter.filterWrite(IoFilterAdapter.java:123)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callPreviousFilterWrite(DefaultIoFilterChain.java:482)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1400(DefaultIoFilterChain.java:47)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.filterWrite(DefaultIoFilterChain.java:775)
at
org.apache.mina.filter.codec.ProtocolCodecFilter.filterWrite(ProtocolCodecFilter.java:331)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callPreviousFilterWrite(DefaultIoFilterChain.java:482)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1400(DefaultIoFilterChain.java:47)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.filterWrite(DefaultIoFilterChain.java:775)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.filterWrite(DefaultIoFilterChain.java:705)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callPreviousFilterWrite(DefaultIoFilterChain.java:482)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.fireFilterWrite(DefaultIoFilterChain.java:475)
at
org.apache.mina.core.session.AbstractIoSession.write(AbstractIoSession.java:494)
at
org.apache.mina.core.session.AbstractIoSession.write(AbstractIoSession.java:439)


As it is states in the javadoc
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html
ConcurrentLinkedQueue#size()
method is *NOT* a constant-time operation.
Actually it seems quite costly as it tries to determine the first element
in a for(;;) loop (
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractCollection.java#AbstractCollection.size%28%29
). Since the stress test adds in the queue constantly i think that there,
the problems begins.

I found a commit related to the following code in DefaultIoChain (
http://mail-archives.apache.org/mod_mbox/mina-commits/201209.mbox/%3c20120928145021.1d32c2388...@eris.apache.org%3E
)

-            s.getWriteRequestQueue().offer(s, writeRequest);
+            WriteRequestQueue writeRequestQueue = s.getWriteRequestQueue();
+
             if (!s.isWriteSuspended()) {
-                s.getProcessor().flush(s);
+                if (writeRequestQueue.size() == 0) {
+                    // We can write directly the message
+                    s.getProcessor().write(s, writeRequest);
+                } else {
+                    s.getWriteRequestQueue().offer(s, writeRequest);
+                    s.getProcessor().flush(s);
+                }
+            } else {
+                s.getWriteRequestQueue().offer(s, writeRequest);
             }
         }


Is this improvement really necessary? The "if
(writeRequestQueue.size() == 0)" statement seems to be causing huge
load for me.


Thank you in advance!

Best regards,

Alex

Reply via email to