内存泄漏在哪里? python - 如何在python中的多处理期间使线程超时?
Posted
技术标签:
【中文标题】内存泄漏在哪里? python - 如何在python中的多处理期间使线程超时?【英文标题】:Where is the memory leak? How to timeout threads during multiprocessing in python? 【发布时间】:2018-07-10 11:23:35 【问题描述】:目前尚不清楚如何在 python 中正确超时 joblib 的 Parallel
的工作人员。其他人也有类似的问题here、here、here 和here。
在我的示例中,我使用 50 个 joblib
工人池和 threading
后端。
并行调用(线程):
output = Parallel(n_jobs=50, backend = 'threading')
(delayed(get_output)(INPUT)
for INPUT in list)
这里,Parallel
在len(list) <= n_jobs
时立即挂起而没有错误,但仅在n_jobs => -1
时才挂起。
为了规避这个问题,人们向instructions 提供了如何使用multiprocessing
为Parallel
函数(上例中的get_output(INPUT)
)创建超时装饰器:
主要功能(装饰):
@with_timeout(10) # multiprocessing
def get_output(INPUT): # threading
output = do_stuff(INPUT)
return output
多处理装饰器:
def with_timeout(timeout):
def decorator(decorated):
@functools.wraps(decorated)
def inner(*args, **kwargs):
pool = multiprocessing.pool.ThreadPool(1)
async_result = pool.apply_async(decorated, args, kwargs)
try:
return async_result.get(timeout)
except multiprocessing.TimeoutError:
return
return inner
return decorator
将装饰器添加到原本可以工作的代码中会导致在约 2 倍超时长度加上 eclipse 崩溃后发生内存泄漏。
装饰器的泄漏点在哪里?
如何在 python 中的多处理期间使线程超时?
【问题讨论】:
我是原来的OP。我的内部功能使用硒。对于 selenium 上下文,我找到了一种直接使内部函数超时的方法。根据您的情况,这可能/可能不适用 - 请告诉我,我会直接回答 在我的帖子下回答。 【参考方案1】:在没有hack 的情况下,无法在 Python 中终止线程。
您遇到的内存泄漏是由于您认为它们已被杀死的线程的积累。为了证明这一点,只需尝试检查您的应用程序正在运行的线程数量,您就会看到它们在缓慢增长。
在底层,ThreadPool
的线程并没有终止,而是一直运行你的函数直到结束。
线程不能被杀死的原因是线程与父进程共享内存。因此,在确保应用程序的内存完整性的同时杀死线程是非常困难的。
Java 开发人员想通了long ago。
如果您可以在单独的进程中运行您的函数,那么您可以轻松地依赖超时逻辑,一旦达到超时,进程本身就会被终止。
Pebble
库已经提供了decorators with timeout。
【讨论】:
感谢您的意见。我尝试使用 Pebble 和其他各种装饰器来超时此功能(即 timeout-decorator 0.4.0)。总之,所有这些都会产生内存泄漏。与您的假设相反,这与超时线程的数量无关,因为在我什至没有看到超时线程的时间内内存使用量急剧增加。另一种解决方案是使用 SIGTERM 和 SIGALRM 但这在 Windows 中不起作用。我现在的解决方案是每 n 分钟重新启动整个代码,确保所有最终挂起的线程也重新启动。 抱歉回复晚了。如果您的程序泄漏内存,您应该做的是确定泄漏的来源。您可以查看this 的帖子。如果您无法防止泄漏,我建议您在单独的进程中运行您的逻辑并通过resource 设施设置内存限制。与timeout
结合使用应该使您的服务足够健壮。以上是关于内存泄漏在哪里? python - 如何在python中的多处理期间使线程超时?的主要内容,如果未能解决你的问题,请参考以下文章
我的 AVFoundation/AVCaptureSession 泄漏内存在哪里?