Понимание влияния производительности на параллельный сервер из-за GIL - PullRequest
0 голосов
/ 01 января 2019

Я немного запутался в том, что происходит с моим кодом ниже.Я создал параллельный сервер для поиска 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))

Я также создалпример клиента, который бомбардирует сервер для вычисления 1-го числа в ряду Фибоначчи.Я также закодировал пример потока мониторинга вокруг клиента, чтобы определить количество запросов, которые клиент может отправить на сервер за одну секунду.

Клиент:

# 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%.

Запуск одного клиента:

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

Запуск еще одного клиента

Однако, когда я открываю другой терминал и отправляю запрос на поиск очень большого числа в последовательности Фибоначчи (работа с интенсивным использованием ЦП), я вижу, что количество запросов / сексуществующие два клиента не затронуты.

Терминал # 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

Это все происходит из-за GIL?Может кто-нибудь, пожалуйста, помогите мне понять, что мне здесь не хватает.

Python версия 3.6.5

...