进程内存变得巨大
我正在使用Tornado CurlAsyncHTTPClient。 当我为每个请求实例化相应的httpclient时,我的进程内存对于阻塞和非阻塞请求都在持续增长。 如果我只有一个httpclient实例(tornado.httpclient.HTTPClient / tornado.httpclient.AsyncHTTPClient)并且重用它们,则不会发生此内存使用增长。
另外如果我使用SimpleAsyncHTTPClient而不是CurlAsyncHTTPClient,这种内存增长不会发生,而不管我如何实例化。
这里是一个示例代码,它重现了这一点,
import tornado.httpclient
import json
import functools
instantiate_once = False
tornado.httpclient.AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')
hc, io_loop, async_hc = None, None, None
if instantiate_once:
hc = tornado.httpclient.HTTPClient()
io_loop = tornado.ioloop.IOLoop()
async_hc = tornado.httpclient.AsyncHTTPClient(io_loop=io_loop)
def fire_sync_request():
global count
if instantiate_once:
global hc
if not instantiate_once:
hc = tornado.httpclient.HTTPClient()
url = '<Please try with a url>'
try:
resp = hc.fetch(url)
except (Exception,tornado.httpclient.HTTPError) as e:
print str(e)
if not instantiate_once:
hc.close()
def fire_async_requests():
#generic response callback fn
def response_callback(response):
response_callback_info['response_count'] += 1
if response_callback_info['response_count'] >= request_count:
io_loop.stop()
if instantiate_once:
global io_loop, async_hc
if not instantiate_once:
io_loop = tornado.ioloop.IOLoop()
requests = ['<Please add ur url to try>']*5
response_callback_info = {'response_count': 0}
request_count = len(requests)
global count
count +=request_count
hcs=[]
for url in requests:
kwargs ={}
kwargs['method'] = 'GET'
if not instantiate_once:
async_hc = tornado.httpclient.AsyncHTTPClient(io_loop=io_loop)
async_hc.fetch(url, callback=functools.partial(response_callback), **kwargs)
if not instantiate_once:
hcs.append(async_hc)
io_loop.start()
for hc in hcs:
hc.close()
if not instantiate_once:
io_loop.close()
if __name__ == '__main__':
import sys
if sys.argv[1] == 'sync':
while True:
output = fire_sync_request()
elif sys.argv[1] == 'async':
while True:
output = fire_async_requests()
这里设置instantiate_once变量为True,并执行python check.py sync或python check.py async。 进程内存不断增加
使用instantiate_once = False,这不会发生。
此外,如果我使用SimpleAsyncHTTPClient而不是CurlAsyncHTTPClient,则内存增长不会发生。
我有python 2.7 / tornado 2.3.2 / pycurl(libcurl / 7.26.0 GnuTLS / 2.12.20 zlib / 1.2.7 libidn / 1.25 libssh2 / 1.4.2 librtmp / 2.3)
我可以用最新的龙卷风3.2重现同样的问题
请帮我理解这种行为并找出将龙卷风作为http库使用的正确方法。
HTTPClient和AsyncHTTPClient被设计为可以重用,所以它总是更有效,而不是一直重新创建它们。 实际上,AsyncHTTPClient会尝试神奇地检测是否存在相同IOLoop上的现有AsyncHTTPClient,并使用该AsyncHTTPClient而不是创建新的。
但即使最好重用一个http客户端对象,也不应该因为你在这里(只要你关闭它们)而泄漏来创建它们中的许多对象。 这看起来像pycurl中的一个错误:https://github.com/pycurl/pycurl/issues/182
使用pycurl 7.19.5和这个hack来避免内存泄漏:
您的龙卷风主文件:
tornado.httpclient.AsyncHTTPClient.configure("curl_httpclient_leaks_patched.CurlAsyncHTTPClientEx")
curl_httpclient_leaks_patched.py
from tornado import curl_httpclient
class CurlAsyncHTTPClientEx(curl_httpclient.CurlAsyncHTTPClient):
def close(self):
super(CurlAsyncHTTPClientEx, self).close()
del self._multi
链接地址: http://www.djcxy.com/p/66925.html