United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4503092 : (so) Selector only supports 63 channels (win)

Details
Type:
Bug
Submit Date:
2001-09-14
Status:
Closed
Updated Date:
2002-05-28
Project Name:
JDK
Resolved Date:
2002-04-25
Component:
core-libs
OS:
windows_nt,windows_2000
Sub-Component:
java.nio
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.1 (hopper)

Related Reports
Duplicate:

Sub Tasks

Description

Name: nt126004			Date: 09/14/2001


java version "1.4.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)

I am using the new java.nio.channels package to write a server application
that needs to support thousands of concurrent users. These are not short
running HTTP requests, but rather long running sessions. The way to go is to
use non-blocking IO. After spending some time figuring out how to use the
package I tried running some stress tests. Everything was fine until I hit
it with more then 62 users, when I did I got the following error:

java.lang.UnsupportedOperationException: Implementation allows only 63 channels
per Selector
        at sun.nio.ch.PollArrayWrapper.addEntry(PollArrayWrapper.java:123)
        at sun.nio.ch.PollSelectorImpl.implRegister(PollSelectorImpl.java:144)
        at sun.nio.ch.SelectorImpl.register(SelectorImpl.java:112)
        at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSele
ctableChannel.java:166)
        at NBTest.startServer(NBTest.java:85)
        at NBTest.main(NBTest.java:111)

63 Channels per selector is utterly useless if you want to write a scalable
server application, the reason for java.nio.channels to exist in the first
place.

I have run the same test on Solaris and on Linux and the problem did not occur
there, although I did need to increase the number of file handles the system
allows for Redhat Linux 7.1

Code to reproduce the problem:

/*
 * NBTest.java
 *
 * Created on 01 September 2001, 21:20
 */

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;

/**
 *
 * @author  Administrator
 * @version
 */
public class NBTest {


    /** Creates new NBTest */
    public NBTest()
    {
    }

    
    private static void debug(String s)
    {
        System.out.println(s);
    }
    
    
    private static void printKeyInfo(SelectionKey sk)
    {
        String s = new String();
        
        s  = "Att: " + (sk.attachment() == null ? "no" : "yes");
        s += ", Read: " + sk.isReadable();
        s += ", Acpt: " + sk.isAcceptable();
        s += ", Cnct: " + sk.isConnectable();
        s += ", Wrt: " + sk.isWritable();
        s += ", Valid: " + sk.isValid();
        s += ", Ops: " + sk.interestOps();
        debug(s);
    }
    
    
    public void startServer() throws Exception
    {
	int		    channels	= 0;
	int		    nKeys	= 0;
        int		    currentSelector = 0;
	Selector	    selector    = Selector.open();
        ServerSocketChannel ssc		= ServerSocketChannel.open();
        InetSocketAddress   address	= new InetSocketAddress
(InetAddress.getLocalHost(),9000);

        ssc.socket().bind(address);
        ssc.configureBlocking(false);
        
        SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
        printKeyInfo(s);

        while(true)
        {
	    debug("NBTest: Starting select");
            nKeys = selector.select();
            if(nKeys > 0)
            {
                debug("NBTest: Number of keys after select operation: " +
nKeys);
                Set selectedKeys = selector.selectedKeys();
                Iterator i = selectedKeys.iterator();
                while(i.hasNext())
                {
                    s = (SelectionKey) i.next();
                    printKeyInfo(s);
                    debug("NBTest: Nr Keys in selector: " + selector.keys().size
());
                    i.remove();
                    if(s.isAcceptable())
                    {
                        // Get the SocketChannel
                        Socket socket = ((ServerSocketChannel) s.channel
()).accept();
                        SocketChannel sc = socket.getChannel();
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ |
SelectionKey.OP_WRITE);
                        System.out.println(++channels);
		    }
                    else
                    {
                        debug("NBTest: Channel not acceptable");
                    }
                }
            }
            else
            {
                debug("NBTest: Select finished without any keys.");
            }

        }
    }
    
    
    /**
    * @param args the command line arguments
    */
    public static void main (String args[])
    {
	NBTest nbTest = new NBTest();
        try
        {
            nbTest.startServer();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

}

Run this application and telnet to port 9000. It doesn't do much, it just
accepts incoming connections and adds those to the selector.
(Review ID: 131555) 
======================================================================

Name: nt126004			Date: 09/14/2001


java version "1.4.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)


The problem is simple, if we try to register more than 63 SocketChannel on one
Selector we get :

java.lang.UnsupportedOperationException: Implementation allows only 63 channels
per Selector
        at sun.nio.ch.PollArrayWrapper.addEntry(PollArrayWrapper.java:123)
        at sun.nio.ch.PollSelectorImpl.implRegister(PollSelectorImpl.java:144)
        at sun.nio.ch.SelectorImpl.register(SelectorImpl.java:112)
        at java.nio.channels.spi.AbstractSelectableChannel.register
(AbstractSelectableChannel.java:166)

For a server more than 63 concurrent sessions is far to be exceptional.

I can see 3 possible origins to this limitation :

1) This limitation is due to the way the implementation of the Selector (or one
of its dependencies) has been done. --> implementation should be extended

2) This limitation has been artificially added because of a performance
degradation due to some native bottleneck on the selection of the socket -->
should eventually let us the choice to go above this limit

3) This is a limitation of the native calls to select a socket --> not much one
can do about it, but it should be documented somewhere.
(Review ID: 131887)
======================================================================

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
hopper

FIXED IN:
hopper

INTEGRATED IN:
hopper

VERIFIED IN:
hopper-beta


                                     
2004-06-14
WORK AROUND



Name: nt126004			Date: 09/14/2001


Customer Workaround:
Create a pool of threads, each hosting its own selector. ALternatively don't
use more then 63 channels while developing your application. I am sure Sun will
remove this limitation before they release the final version of 1.4
======================================================================

Name: nt126004			Date: 09/14/2001


Customer Workaround:
We have to use several Selector.
The problem there is that its not possible to register a new channel for a
selector if the selector is blocked on a select().

Since the wakeup() method is currently not working on NT (reported bug
4467968), some not so nice alternatives could be used:
- use select(long timeout)
- interrupt the thread...
- act on a dedicated registered Socket to encourage the select to wake up
(Review ID: 131887)
======================================================================
                                     
2004-06-11
PUBLIC COMMENTS

Now we have a new Selector implementation for Windows, which can support
thousands of channels.
                                     
2004-06-10
EVALUATION

This is a known problem that only affects Windows platforms, and is due to the
fact that WaitForMultipleObjects can only handle 64 events at a time.  A fix is
in progress and is slated for the 1.4.1 release.

-- ###@###.### 2002/3/22

                                     
188-10-03 0



Hardware and Software, Engineered to Work Together