2006年11月22日

这是6.0之前的poll模型。
solaris\native\sun\nio\ch\SocketChannelImpl.c
JNIEXPORT jint JNICALL
Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv 
*env, jobject this,
                           jobject fdo, jboolean block,
                                               jboolean ready)
{
    
int error = 0;
    
int n = sizeof(int);
    jint fd 
= fdval(env, fdo);
    
int result = 0;
    struct pollfd poller;

    poller.revents 
= 1;
    
if (!ready) {
        poller.fd 
= fd;
        poller.events 
= POLLOUT;
        poller.revents 
= 0;
        result 
= poll(&poller, 1, block ? -1 : 0);
        
if (result < 0) {
            JNU_ThrowIOExceptionWithLastError(env, 
"Poll failed");
            
return IOS_THROWN;
        }
    
if (!block && (result == 0))
        
return IOS_UNAVAILABLE;
    }

    
if (poller.revents) {
        errno 
= 0;
        result 
= getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
        
if (result < 0) {
            handleSocketError(env, errno);
            
return JNI_FALSE;
        } 
else if (error) {
            handleSocketError(env, error);
            
return JNI_FALSE;
        }
        
return 1;
    }
    
return 0;
}


6.0缺省的模型是使用epoll
E:\Java\jdk-6-rc-src\j2se\src\solaris\native\sun\nio\ch\EPollArrayWrapper.c

JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_init(JNIEnv 
*env, jclass this
{
    epoll_create_func 
= (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create");
    epoll_ctl_func    
= (epoll_ctl_t)    dlsym(RTLD_DEFAULT, "epoll_ctl");
    epoll_wait_func   
= (epoll_wait_t)   dlsym(RTLD_DEFAULT, "epoll_wait");
                                                                                                   
    
if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) ||
        (epoll_wait_func 
== NULL)) {
        JNU_ThrowInternalError(env, 
"unable to get address of epoll functions, pre-2.6 kernel?");
    }
}


具体程序的流程我还是不够清楚,还有待进一步深入了解。
posted @ 2006-11-22 01:34 温少的日志 阅读(3222) | 评论 (2)编辑 收藏
 
java 1.4提供了nio,也就是之前我的一片博客中所说的multiplexed non-blocking I/O。这种模型比阻塞模型的并发性能要好一些,Java很多的网络应用都因此重写了底层模块,包括Tomcat、Jetty等等,也出现了基于nio的框架mina、国产的cindy等等。

java nio带来的影响是巨大的,得到了很多拥护和赞赏。

不过有一些是谣言,例如windows下的实现是Windows中并发性能最好的I/O模型IOCP,但事实上是这样么?

JDK 6.0 RC版提供了源码下载,下载路径:http://www.java.net/download/jdk6/jdk-6-rc-src-b104-jrl-01_nov_2006.jar

我们看最终Windows的实现:
j2se\src\windows\native\sun\nio\ch\WindowsSelectorImpl.c


82行开始:
    /* Call select */
    
if ((result = select(0 , &readfds, &writefds, &exceptfds, tv)) 
                                                             
== SOCKET_ERROR) {
        
/* Bad error - this should not happen frequently */
        
/* Iterate over sockets and call select() on each separately */
        FD_SET errreadfds, errwritefds, errexceptfds;
        readfds.fd_count 
= 0;
        writefds.fd_count 
= 0;
        exceptfds.fd_count 
= 0;
        
for (i = 0; i < numfds; i++{
            
/* prepare select structures for the i-th socket */
            errreadfds.fd_count 
= 0;
            errwritefds.fd_count 
= 0;
            
if (fds[i].events & POLLIN) {
               errreadfds.fd_array[
0= fds[i].fd;
               errreadfds.fd_count 
= 1;
            }

            
if (fds[i].events & (POLLOUT | POLLCONN)) {
                errwritefds.fd_array[
0= fds[i].fd;
                errwritefds.fd_count 
= 1;
            }

            errexceptfds.fd_array[
0= fds[i].fd;
            errexceptfds.fd_count 
= 1;

            
/* call select on the i-th socket */
            
if (select(0&errreadfds, &errwritefds, &errexceptfds, &zerotime) 
                                                             
== SOCKET_ERROR) {
                
/* This socket causes an error. Add it to exceptfds set */
                exceptfds.fd_array[exceptfds.fd_count] 
= fds[i].fd;
                exceptfds.fd_count
++;
            }
 else {
                
/* This socket does not cause an error. Process result */
                
if (errreadfds.fd_count == 1{
                    readfds.fd_array[readfds.fd_count] 
= fds[i].fd;
                    readfds.fd_count
++;
                }

                
if (errwritefds.fd_count == 1{
                    writefds.fd_array[writefds.fd_count] 
= fds[i].fd;
                    writefds.fd_count
++;
                }

                
if (errexceptfds.fd_count == 1{
                    exceptfds.fd_array[exceptfds.fd_count] 
= fds[i].fd;
                    exceptfds.fd_count
++;
                }

            }

        }

    }
            

这就是广泛应用在Winsock中使用的select模型,也众所周知,并发性能不是很好。而且FD_SETSIZE不能超过Windows下层提供者的限制,这个限制通常是1024。也就是说Windows下,JDK的nio模型,不能超过1024个连接,这个跟我之前做的测试结果相似。

而且,如果FD_SETSIZE很大的话,例如是1000,调用select之前,必须设置1000个socket,返回之后又必须检查这1000个socket。

也就说,Windows下使用SUN JDK java的nio,并不能提高很好的并发性能。
posted @ 2006-11-22 00:35 温少的日志 阅读(3563) | 评论 (1)编辑 收藏