python - Flask 中有 python GIL 吗?
问题描述
我最近在研究python多线程,我发现GIL会强制python一次运行一个线程,即使在多核CPU上也是如此。
所以我做了一些小PoC。
我的代码如下:
import threading
import time
COUNT = 50000000
def count():
i = 0
print('thread id =', threading.get_ident())
while(i < COUNT):
i = i +1
start_time = time.time()
count()
count()
end_time = time.time()
print(f'execution time without multiple threading : {end_time - start_time}')
start_time = time.time()
t_1 = threading.Thread(target=count)
t_2 = threading.Thread(target=count)
t_1.start()
t_2.start()
t_1.join()
t_2.join()
end_time = time.time()
print(f'execution time with multiple threading : {end_time - start_time}')
这是我的结果:
thread id = 2204
thread id = 2204
execution time without multiple threading : 5.695769786834717
thread id = 3492
thread id = 5260
execution time with multiple threading : 5.339878082275391
这很清楚 GIL 的工作原理。
但现在我在 Flask 上做同样的过程,看起来 GIL 没有按预期工作。这是我的代码:
服务器.py
from flask import Flask
import threading
import os
app = Flask(__name__)
COUNT = 50000000
@app.route('/')
def hello():
print ('Thread id = ', threading.get_ident())
print ('Process id = ', os.getpid())
i = 0
while(i < COUNT):
i = i +1
return "Hello World!"
if __name__ == '__main__':
app.run()
客户端.py
import requests
import time
import multiprocessing as mp
def send():
start_time = time.time()
r = requests.get('http://localhost:5000')
end_time = time.time()
print(f'response after {end_time - start_time}')
if __name__ == '__main__':
p_1 = mp.Process(target=send)
p_2 = mp.Process(target=send)
p_1.start()
p_2.start()
p_1.join()
p_2.join()
server.py 的结果:
Thread id = 18428
Process id = 19000
Thread id = 17436
Process id = 19000
127.0.0.1 - - [14/Sep/2020 09:36:19] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [14/Sep/2020 09:36:19] "GET / HTTP/1.1" 200 -
client.py 的结果
response after 7.361770153045654
response after 7.373677015304565
似乎有 2 个客户端同时获得响应,但是使用 GIL,我的预期结果应该是 7.3 第一个响应和 14.xxx 在第二个响应。谁能帮我验证这个问题?
解决方案
Python Flask 中也有一个 GIL 在我问的问题中,我没有单独向服务器发送请求。实际上,单个请求需要一半的时间才能得到响应。为什么我们可以同时得到两个响应?这是因为其中有 sys.getswitchinterval() ,所以线程将每 0.005 秒切换一次,直到它们完成工作。
推荐阅读
- c# - 比较复杂结构 C# 中的 N 个对象
- prolog - 提取 Prolog 树的最小值
- c# - 从 VisulaStudio 项目中抑制或删除 CA0068 CA 警告
- amazon-web-services - cloudformation 堆栈中的内部转换错误
- swift - NSView 获得焦点的方向(标签或后退标签)?
- iis - 每个处理器的 IIS 8.5 线程数限制
- laravel - 社交名媛 Google redirect_uri_mismatch
- python - 没有 NaN 值空间的 Pandas 绘图条
- reactjs - 如何对 Electron 应用程序进行性能测试?
- activemq-artemis - 消息历史记录和 Jolokia MBean