具有阻塞I / O的Python多线程

时间:2016-03-24 01:43:02

标签: python multithreading performance io gil

我的应用程序使用多个I / O阻塞(网络)请求,需要一段时间才能完成。 我尝试使用多线程但它似乎没有带来任何加速,我猜它与Python的GIL有关。

事情是所有请求可以同时完成,并且彼此之间没有依赖关系。如何解决此性能问题?

我的代码

import threading
import urllib2
import time
def send_request(url, count_str):
    start_time = time.time()
    urllib2.urlopen(url)
    print "Request " + count_str + " took " + str(time.time() - start_time) + " started at " + str(start_time)

count = 0
for url in open('urllist.txt'):
    t = threading.Thread(target=send_request, args = (url.strip(), str(count)))
    t.start()
    count+=1

输出

Request 1 took 5.0150949955 started at 1458789266.78
Request 2 took 10.0112490654 started at 1458789266.79
Request 0 took 15.024559021 started at 1458789266.78
Request 3 took 20.016972065 started at 1458789266.79

urllist.txt中的url指向我在本地运行的服务器需要5秒钟才能响应。 你可以看到他们都在同一时间“开始”,但他们正在阻止。

2 个答案:

答案 0 :(得分:2)

我无法重现您的问题(当针对少数互联网服务器进行测试时,每次重复几次,所有请求都在大约相同的时间内完成,没有稳定增加的延迟),但是您的新输出指向完全不同的问题:我怀疑您使用的“本地服务器”可能不是多线程的(或者能够同时为多个请求提供服务)。

您自己的输出表明线程并行启动,但请求是串行服务的;如果是GIL切换导致问题,我希望看到所有这些都延迟了一点(一个线程会完成一些工作,然后另一个会做更多,等等),而不是每个都在下一次启动之前运行完成。这在服务器端存在问题,服务器在服务其他连接之前处理完成请求。

尝试精神调试,你有没有机会通过在服务器代码中添加一个睡眠来实现五秒请求时间,可能是在accept返回之后,但是在启动一个线程来服务它之前?或者根本不在服务器上使用线程?

答案 1 :(得分:-1)

Python线程很慢! Python有一个GIL(全局解释器锁),它使用互斥锁来序列化对内部的访问。您可能希望了解一下没有GIL的Jython,并且可以完全利用多处理器系统。