簡體   English   中英

epoll +非阻塞套接字比阻塞+超時慢嗎?

[英]epoll + non-blocking socket slower than blocking + timeout?

我有兩個用python編寫的簡單套接字服務器版本。 第一個版本使用epoll +無阻塞方式,並且似乎比具有阻塞套接字+超時的服務器版本要慢得多。

非阻塞服務器產生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)

這是客戶。 它僅在環路中連接到服務器並關閉連接。 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 +無阻塞循環中會有一些延遲?

謝謝!!!

epoll()對於(從聯機幫助頁epoll(2)來)非常有用:監視多個文件描述符,以查看是否可以在任何文件描述符上進行I / O。

您正在使用epoll()監視一個文件描述符。 就上下文切換而言,這增加了很多開銷; 每個孩子都必須調用epoll_create(),epoll_ctl()和epoll_wait()。 接着! 每個新連接都會喚醒他們。 接着! 他們中的大多數都沒有接受。

在阻止版本中,可能只有一個孩子被喚醒。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM