我正在运行数千个异步任务。
大约需要10秒钟才能完成(某些CPU密集型工作)。
这使程序无法正常工作,因为某些任务需要在5秒内回答其网络连接上的消息。
我当前的想法是以某种方式拦截事件循环。 在异步模块中,必须在每个epoll()/ select()之间的某个事件循环中执行所有当前活动任务的区域。如果我可以在每个任务“恢复”之前插入“ elapsed = time.time()”,然后在“恢复”之后插入“ elapsed = time.time()-经过”,那么我认为找出占用过多任务的足够了时间。
我认为相关代码可能在此处,第79行: https://github.com/python/cpython/blob/master/Lib/asyncio/events.py
def _run(self):
try:
self._context.run(self._callback, *self._args)
except (SystemExit, KeyboardInterrupt):
raise
except BaseException as exc:
cb = format_helpers._format_callback_source(
self._callback, self._args)
msg = f'Exception in callback {cb}'
context = {
'message': msg,
'exception': exc,
'handle': self,
}
if self._source_traceback:
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)
self = None # Needed to break cycles when an exception occurs.
但是我不知道该怎么做以打印任何有用的信息。我需要一种方法来确定“ self._context.run(...)”将在我的代码的哪一行执行。
过去5个不眠之夜,我试图修复自己的代码,但还没有成功。
我尝试使用CProfiler,line_profile,但是它们都没有帮助。 他们告诉我执行一个功能需要花费的时间以及每行花费的时间。我需要找出的是每次循环迭代之间要花费多少时间。
我尝试过的所有概要分析/调试工具都给我不了什么应该解决的线索。而且以不同的方式重写相同的程序约15次之后,我仍然无法正常运行。
我只是一个非专业的程序员,还是Python的新手,但是如果我不能解决这个问题,那么下一步将是学习学习Rust,这本身将是一个巨大的痛苦,大概在三年后我开始工作,将使该功能正常运行,该过程应该不会超过2个月。
答案 0 :(得分:1)
顺便说一句,asyncio
内部有一个很酷的功能(你可以看代码来源:here),它会告诉你是否有“阻塞”功能。
您只需要启用调试模式(适用于负载测试)。
如何启用调试模式 - 您可以找到here所有选项如何。
答案 1 :(得分:0)
只需编辑文件/usr/lib/python3.7/asyncio/events.py并添加:
import time
import signal
import traceback
START_TIME = 0
def handler(signum, frame):
print('##########', time.time() - START_TIME)
traceback.print_stack()
signal.signal(signal.SIGALRM, handler)
第79行:
def _run(self):
global START_TIME
try:
signal.alarm(3)
START_TIME = time.time()
self._context.run(self._callback, *self._args)
signal.alarm(0)
except Exception as exc:
cb = format_helpers._format_callback_source(
self._callback, self._args)
msg = f'Exception in callback {cb}'
context = {
'message': msg,
'exception': exc,
'handle': self,
}
if self._source_traceback:
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)
self = None # Needed to break cycles when an exception occurs.
现在,每次异步代码阻塞事件循环3秒钟,它将显示一条消息。
发现我的问题是一个简单的“ BeautifulSoup(page,'html.parser')”,其中页面是一个1mb的html文件,带有一个大表。