Memory Zeromq内存泄漏(pyzmq)
嗨,我正在尝试使用呼吸机/工作者/接收器模式使用ZeroMQ发送大数据包 我试着增加工人。每一次,接收器进程内存使用都会略有增加。然后,在大约6或7个工作人员的情况下,它达到了一个临界点,在这个临界点上,内存突然呈指数级增长,直到它因以下原因而死亡:Memory Zeromq内存泄漏(pyzmq),memory,python-2.7,zeromq,pyzmq,Memory,Python 2.7,Zeromq,Pyzmq,嗨,我正在尝试使用呼吸机/工作者/接收器模式使用ZeroMQ发送大数据包 我试着增加工人。每一次,接收器进程内存使用都会略有增加。然后,在大约6或7个工作人员的情况下,它达到了一个临界点,在这个临界点上,内存突然呈指数级增长,直到它因以下原因而死亡: > *** error: can't allocate region > *** set a breakpoint in malloc_error_break to debug Assertion failed: (msg_->f
> *** error: can't allocate region
> *** set a breakpoint in malloc_error_break to debug Assertion failed: (msg_->flags | ZMQ_MSG_MASK) == 0xff (zmq.cpp:211)
> Python(42410,0xaccb8a28) malloc: *** mmap(size=3559424) failed (error
> code=12)
以下是代码(仅显示工作/接收模式):
这仅仅是因为缺乏硬件资源吗?积压的数据?还是有办法避免这种情况
我正在使用16gb内存运行OSX Mountain Lion,使用zmq 2.2.0.1运行Python 2.7
谢谢
这仅仅是因为缺乏硬件资源吗
好吧,让我们来算一下。每个工人每10ms发送3.3MB。或者大约每秒300mb。现在添加更多的工人。当您最多有5名工作人员时,每秒发送的数据量约为1.5GB
我想你已经找到了你机器的性能极限。当接收器进程与所有工作进程在同一台机器上运行时,它能够每秒消耗1-2GB。当数据传入的速度快于此时,队列在接收器进程中的累积速度快于清空数据的速度,并且内存不足
还是有办法避免这种情况
发送较小的消息?不那么频繁?:)或者把工人和水槽放在不同的机器上。请记住,工人正在从接收器窃取CPU资源。如果这是一台四核机器,那么在接收器加上最多3个工作线程的情况下,操作系统可能会将几乎所有的处理器核心分配给每个进程
一旦添加了第4、第5、第6个工作进程,操作系统就无法为任何进程提供100%的内核。他们必须开始共享,因此即使消息速度加快,接收器也会减慢速度。这就解释了内存使用呈指数增长的临界点
嗯,这意味着一个有趣的实验。你能配置你的mac让接收器进程以一个非常高的优先级运行吗?这可能会带来更好的结果。我自己从来没有尝试过这个,但请查看以下链接以获取想法 谢谢你。我试过用nicing,但没用,但肯定是因为缺乏网络。正如你所说,我可能会沉在一个单独的盒子里。如果必要的话,我甚至可能有多个水槽。这确实表明,我最好不要把它分散在多个盒子上。相对于网络传输限制,计算时间太少。我最好在ec2上安装20个计算单元,然后在那里完成所有的工作。我想知道在一个hadoop作为所有此类任务的解决方案被出售的世界里,这种情况发生的频率有多高。当然,它不仅仅是上面提到的,但也不仅仅是一个以制表符分隔的文本分割和一些计数和过滤。我试着让工作人员拥有最低优先级。它也没有帮助注意到ZeroMQ:s队列的默认值设置为1000。如果缓冲区中的消息大小为3.3MB,则该缓冲区中的消息大小为3.3GB。每个发布者为每个订阅者持有一个单独的队列,这意味着您很快就会用完这里的mem。不过,队列大小是可调整的。我不确定接收器是否为每个传入的工作者保留一个队列,但这是可能的。
import sys
import resource
import zmq
import time
context = zmq.Context()
if sys.argv[1] == 'worker':
# Socket to send messages to
sender = context.socket(zmq.PUSH)
sender.connect("tcp://localhost:5558")
while True:
msg = 'x' * 3559333
time.sleep(.01)
sender.send(msg)
else:
# Socket to receive messages on
receiver = context.socket(zmq.PULL)
receiver.bind("tcp://*:5558")
while True:
msg = receiver.recv()
print msg[0:5], len(msg), resource.getrusage(resource.RUSAGE_SELF).ru_maxrss