了解由于GIL对并发服务器的性能影响

时间:2019-01-01 08:53:39

标签: python python-internals gil

我对下面的代码所发生的事情感到困惑。我创建了一个并发服务器来查找斐波那契数列中的第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))

我还创建了一个示例客户端,该客户端轰击服务器以计算斐波那契数列中的第一个数字。我还在客户端周围编写了一个示例监视线程,以查找客户端能够在一秒钟内发送到服务器的请求数量。

客户

# 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 req / sec)。但是当我再运行一个客户端时,我发现每个客户端的请求数/秒降低了50%。

运行一个客户端:

Terminal#1

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

再运行一个客户端:

Terminal#2

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

Termina#1

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

再运行一个客户端

但是,当我打开另一个终端并提交请求以按斐波那契顺序查找大量(CPU密集型作业)时,我发现现有两个客户端的请求/秒没有受到影响。

Terminal#3

$ nc localhost 25000
50
_

Terminal#2

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

Termina#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

这一切都是因为GIL发生了吗?有人可以帮我了解我在这里想念的东西吗。

Python版本3.6.5

0 个答案:

没有答案