2014-11-05 5 views
0

파이썬으로 작성된 간단한 소켓 서버의 두 가지 버전이 있습니다. 첫 번째 버전은 epoll + nonblocking aproach를 사용하며 소켓 + 타임 아웃을 차단하는 서버 버전보다 느린 것으로 보입니다.epoll + non-blocking 소켓이 blocking + timeout보다 느린가요?

비 차단 서버는 10 명의 어린이와 어린이가 소켓에서 수락합니다. 이 경우 모든 아이들은 EPOLLIN 통보를 받고 있지만, 오직 하나의 자식 만 받아들이면 , 다른 모든 자식은 EAGAIN이 될 것이고 이것은 "except-block"에 의해 무시됩니다.

--- server-nonblocking.py ---

import socket, time, os, select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('127.0.0.1', 10000)) 
sock.listen(512) 
sock.setblocking(False) 


for _ in range(0,10): 

    pid = os.fork() 
    if pid == 0: #in child 
     poll = select.epoll() 
     poll.register(sock.fileno(), select.EPOLLIN) 

     while True: 
      events = poll.poll(3) # listening for events with 2 sec timeout 
      for fileno, event in events: 
       if event & select.EPOLLIN: # there is data on socket available 
        print("EPOLLIN in PID: " + str(os.getpid())) 
        try: 
         clientsock, addr = sock.accept() 
         clientsock.close() 
         print("accepted and closed in PID: " + str(os.getpid())) 
        except: 
         pass 


# we are in parent process, keep it live 
while True: 
    time.sleep(10) 

블로킹 서버도 10 자녀를 생성합니다 대신 소켓을 듣고에 제한 시간을 사용, 제한 시간은 except 블록에 의해 차단 무시됩니다

--- server-blocking.py ---

import socket, time, os, select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('127.0.0.1', 10000)) 
sock.listen(512) 
sock.settimeout(5) 


for _ in range(0,10): 

    pid = os.fork() 
    if pid == 0: #in child 
     while True: 
      try: 
       clientsock, addr = sock.accept() 
       clientsock.close() 
       print("accepted and closed in PID: " + str(os.getpid())) 
      except: 
       pass 


# we are in parent process, keep it live 
while True: 
    time.sleep(10) 

그녀를 e는 클라이언트입니다. 그것은 단지 루프에서 서버에 연결하고 연결을 닫습니다. 20 초 후. 루프가 중단됩니다.

--- client.py ---

import socket, time, select, sys 

i = 1 
td = time.time() 
while True: 
    print("loop " + str(i) + ", time: " + str(time.time() - td)) 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect(('localhost',10000)) 
    s.setblocking(False) 
    s.close() 
    i += 1 
    if time.time() - td >= 20: 
     break 

그리고 여기에 두 서버의 결과는 다음과 같습니다 방법을 비보다 더 많은 연결을 처리 할 수있는 서버를 차단

blocking: 
loop 137670, time: 19.99994468688965 

non-blocking: 
loop 94051, time: 19.10340452194214 

차단 서버. 클라이언트가 비 차단 버전을 사용할 때 루프에서 지연이 발생할 수 있습니다.

누군가가이 동작을 설명 할 수 있습니까? epoll + non-blocking에서 루프가 지연되는 이유는 무엇입니까?

감사합니다 !!!

답변

1

epoll()은 여러 파일 기술자를 모니터링하여 그 중 어느 것이나 입출력이 가능한지 확인하는 데 유용합니다 (epoll (2) 매뉴얼 페이지).

하나의 파일 설명자를 모니터하기 위해 epoll()을 사용하고 있습니다. 이는 컨텍스트 스위치와 관련하여 많은 오버 헤드를 추가합니다. 각 어린이는 epoll_create(), epoll_ctl() 및 epoll_wait()를 호출해야합니다. 그리고! 그들은 모든 새로운 연결에 대해 모두 깨어납니다. 그리고! 그들 대부분은 받아 들일 수 없다.

차단 버전에서는 아마 하나의 자식 만 깨어납니다.