1

I get the following code snippet:

datagramChannel = DatagramChannel
    .open(StandardProtocolFamily.INET).setOption(StandardSocketOptions.SO_REUSEADDR, true)
    .setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
datagramChannel.configureBlocking(true);
datagramChannel.bind(new InetSocketAddress(filter.getType()
    .getPort(filter.getTimeFrameType())));
datagramChannel.join(group, networkInterface);
datagramChannel.receive(buffer);

This code is located in a Callable and I create up to 12 Callables (12 threads thus) to retrieve multicast packets with different data from 12 different ports. It only reads from the information which is broacasted on the network each 3-8 seconds.

When pooling the 12 ports continuously (wait for the information, get the information, and so on), it eats 100% of one of my CPU.

Profiling the execution with JVisualVM, I see that 90% of the execution time is devoted to java.nio.channels.DatagramChannel#receive(), and more precisely com.sun.nio.ch.DatagramChannelImpl#receiveIntoBuffer().

  1. I don't understand well why the blocking mode eat so much CPU.

  2. I have read some articles on using Selectors instead of blocking mode, but I don't really see why a while (true) with Selector would be less consuming than a blocking channel.

Doc Davluz
  • 4,154
  • 5
  • 30
  • 32
  • You aren't 'polling the 12 ports continuously', unless there is a very short read timeout being set that you aren't showing us. You are reading from one port at a time, in blocking mode. I hope you aren't doing all this socket creation and binding and joining every time around the loop. – user207421 Feb 17 '14 at 10:25
  • When I say 'polling the 12 ports continuously', I mean that information on the 12 ports is broadcasted simultaneously, and that once read, I go for another round of wait and read. The read timeout is around 5 seconds on each port. Indeed, I'm not doing the whole creation and binding each time. – Doc Davluz Feb 17 '14 at 11:10

1 Answers1

1

The problem is you are using NIO without Selector.

NIO without Selector is ok to use but then Channel.receive would be constantly trying to read which would show up as high CPU usage for one thread.

There are 2 solutions :-

  • Use Selector to detect if there is something to read. Call channel.receive only when Selector indicates there is data to be read
  • Use java.net.DatagramSocket/DatagramPacket to send/receive in blocking mode.
rajeshnair
  • 1,587
  • 16
  • 32
  • Thanks for those hints. I'm not working on this code anymore sadly, but I will test that on a sample piece of code. – Doc Davluz Nov 10 '14 at 08:51