Hi ! I conducted some profiling sessions today, to see where we were spening some spurious CPU in MINA3. When I first did some tests, I was able to process 1 million 10 bytes messages in 75 seconds (the message is written by the client, read by the server, which returns a 1 bte message to the client). This is the very same test than the one Jeff wrote for MINA 2 and Netty.
After a bit of analysis, I was able to lower this number to 57 seconds. Now, here are the numbers for MINA 3, MINA 2 and Netty, for 1M messages : Mina3 client/ Mina3 server : 10bytes msgs in 57.8 secs | 1k msgs in 53.2 secs | 10k msgs in 66.1 secs Mina2 client/ Mina2 server : 10bytes msgs in 53.4 secs | 1k msgs in 52.4 secs | 10k msgs in 75.6 secs Netty client/ Mina2 server :10bytes msgs in 51.4 secs | 1k msgs in 49.6 secs | 10k msgs in 74.7 secs (we currently don't have a Netty server) So bottom line, MINA 3 is slower than any other combinaison, despite the minimal features we have injected, except for big messages. Is this a problem ? Well, yes and no. There are some very good reasons for MINA 3 to be slower : we call the selector.select() method for every message we have to send. This is the most expensive part of the code, and it's not something we can improve : we don't have any way to make select() go faster. OTOH, we could call select() less often. Right now, what we do is that everytime we exit from a select(), we process all the activated SelectionKey we get. This is done by calling the ready() method, with flags indicating which event we have to process (OP_READ and OP_WRITE mainly). The ready() method processes the connect, read, wrate and accept events, one after the other. The thing here is that if a read results in some writes, the writes will be processed in the next select() loop, when in Netty and MINA2 it's potentially processed just afterward, in the same select() loop. We can bypass this extra loop most of the time, as soon as the channel is ready. The idea is to push the message into the channel, if we don't have anything in the writeQueue, and we are done. If the writeQueue is not empty, we simply push the message in the queue. Last, not least, if we weren't able to write all the message, we push the remaining message on the writeQueue, set the SelectKey OP_WRITE to true, and wake up the selector. That would save us a lot of CPU for small messages. I will try to do that. -- Regards, Cordialement, Emmanuel Lécharny www.iktek.com
