Why is MulticastSocket.setNetworkInterface() much slower using Java 8 runtime?

1.3k views Asked by At

I am running the following program, which is much slower when I use a Java 8 runtime compared to a Java 7 runtime.

public class MulticastTest {

    public static void main(String args[]) throws Exception {
        long start = System.nanoTime();
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        MulticastSocket multicastSocket = new MulticastSocket(6665);
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface iface = networkInterfaces.nextElement();
            try {
                multicastSocket.setNetworkInterface(iface);
            } catch (IOException e) {
            }
        }
        long durationMillis = (System.nanoTime() - start) / 1000000;
        System.out.println("Took " + durationMillis + " millis");
    }
}

When I run this on java 8 it takes about 3500 milliseconds. On Java 7 it takes about 150 milliseconds.

I am using the following java versions:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

and

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

I am on Windows 7, service pack 1, specifics:

OS Name:                   Microsoft Windows 7 Professional
OS Version:                6.1.7601 Service Pack 1 Build 7601

My machine has 25 different interfaces (a lot of virtual ones), but the operation takes about the same time for each interface.

Some of the calls fail, but even the successful calls are slow. An interesting fact is that the error message on failed operations are different between Java versions:

Java 7:

java.net.SocketException: An invalid argument was supplied
        at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
        at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(TwoStacksPlainDatagramSocketImpl.java:145)
        at java.net.AbstractPlainDatagramSocketImpl.setOption(AbstractPlainDatagramSocketImpl.java:309)
        at java.net.MulticastSocket.setNetworkInterface(MulticastSocket.java:550)

Java 8:

java.net.SocketException: bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface
        at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
        at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(Unknown Source)
        at java.net.AbstractPlainDatagramSocketImpl.setOption(Unknown Source)
        at java.net.MulticastSocket.setNetworkInterface(Unknown Source)

Running jstack I see the most time spent in the following thread stack:

main" #1 prio=5 os_prio=0 tid=0x0000000002248000 nid=0x1554 runnable [0x00000000026da000]
  java.lang.Thread.State: RUNNABLE
   at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
   at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(TwoStacksPlainDatagramSocketImpl.java:146)
   at java.net.AbstractPlainDatagramSocketImpl.setOption(AbstractPlainDatagramSocketImpl.java:310)
   at java.net.MulticastSocket.setNetworkInterface(MulticastSocket.java:554)

I have tried disabling all windows firewalls but that made no difference.

The program itself might mot make much sense but I am trying to troubleshoot an issue with a third party platform which runs this kind of code, why rewriting it is not an option.

The problem is reproducable on other workstations in our office.

Any ideas what could cause this behavior or how I could troubleshoot it further?

1

There are 1 answers

0
brianjriddle On

This looks like an issue with ipv6.

If I run your program locally this takes 1561 millis to run.

If I disable the ipv6 stack with -Djava.net.preferIPv4Stack=true it takes about 100 mills.

Of note is that with ipv6 enabled this program sees 7 interfaces on my machine but only 4 interfaces when only using ipv4.