代码之家  ›  专栏  ›  技术社区  ›  Lokesh Agrawal

理解GIL对并发服务器性能的影响

  •  4
  • Lokesh Agrawal  · 技术社区  · 7 年前

    我对下面的代码有点困惑。我创建了一个并发服务器来查找fibonacci级数中的第n个数。服务器为每个客户端连接创建一个线程,线程将查找斐波那契数列中斐波那契数的计算委托给单独的进程。

    服务器

    # server.py
    # Fibonacci Microservice
    
    from socket import *
    from fib import fib
    from threading import Thread
    from concurrent.futures import ProcessPoolExecutor as Pool
    
    
    pool = Pool(4)
    
    
    def fib_server(address):
        sock = socket(AF_INET, SOCK_STREAM)
        sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.bind(address)
        sock.listen(5)
    
        while True:
            client, addr = sock.accept()
            print("Connection", addr)
            Thread(target=fib_handler, args=(client,), daemon=True).start()
    
    
    def fib_handler(client):
        while True:
            req =  client.recv(100)
            if not req:
                break
            n = int(req)
            future = pool.submit(fib, n)
            result = future.result()
            resp = str(result).encode('ascii') + b'\n'
            client.send(resp)
        print('Closed')
    
    
    fib_server(('', 25000))
    

    我还创建了一个示例客户机,它轰炸服务器以计算fibonacci级数中的第一个数。我还围绕客户机编写了一个示例监视线程,以查找客户机能够在一秒钟内发送到服务器的请求数。

    客户:

    # perf.py
    # requests/sec of fast requests
    
    from socket import *
    import time
    from threading import Thread
    
    sock = socket(AF_INET, SOCK_STREAM)
    sock.connect(('localhost', 25000))
    
    n = 0
    
    
    def monitor():
        global n
        while True:
            time.sleep(1)
            print(n, 'reqs/sec')
            n = 0
    
    
    Thread(target=monitor).start()
    
    while True:
        sock.send(b'1')
        resp = sock.recv(100)
        n += 1
    

    现在,当我从一个终端运行客户机时,我看到每秒的请求率相当高(大约1900个请求/秒)。但是当我运行一个客户机时,我发现每个客户机的请求/秒减少了50%。

    运行一个客户端:

    终端#1

    $ python perf2.py 
    1891 reqs/sec
    1863 reqs/sec
    1813 reqs/sec
    

    再运行一个客户端:

    2号航站楼

    $ python perf2.py 
    1098 reqs/sec
    1080 reqs/sec
    1080 reqs/sec
    

    终点站1

    $ python perf2.py 
    1891 reqs/sec
    1863 reqs/sec
    1813 reqs/sec 
    1089 reqs/sec
    1091 reqs/sec
    1034 reqs/sec
    

    运行另一个客户端

    然而,当我打开另一个终端并提交一个请求来在Fibonacci序列(CPU密集型作业)中找到非常大的数时,我发现现有两个客户端的Reqs/SEC不受影响。

    3号航站楼

    $ nc localhost 25000
    50
    _
    

    2号航站楼

    $ python perf2.py 
    1098 reqs/sec
    1080 reqs/sec
    1080 reqs/sec
    1078 reqs/sec
    

    终点站1

    $ python perf2.py 
    1891 reqs/sec
    1863 reqs/sec
    1813 reqs/sec 
    1089 reqs/sec
    1091 reqs/sec
    1034 reqs/sec
    1058 reqs/sec
    

    这一切都是因为吉尔吗?有人能帮我弄明白我在这里遗漏了什么吗。

    Python 3.6.5版

    0 回复  |  直到 7 年前