当queue.put()的速度比queue.get()速度快时,我发现P1进程将使用大内存(因为P1不断地从大文本文件中放入行)。甚至P2也随后从队列中排队。 P1使用的内存仍然没有释放。如何解决这个问题?以下是示例和测试代码。
谢谢!
import time
from multiprocessing import Process, Queue
def addline(q):
f = file('a big text file','r')
line = True
while line:
line = f.readline()
q.put(line, False)
f.close()
print "P1:finished"
while 1:
time.sleep(2)
def getline(q):
f = file('/tmp/bak','w')
line = True
while line:
line=q.get()
f.write(line)
time.sleep(0.01)
f.close()
print "p2:finished"
if __name__ == "__main__":
q = Queue()
p1 = Process(name="addline", target=addline, args=(q,))
p2 = Process(name="getline", target=getline, args=(q,))
p1.start()
p2.start()
修改 我尝试读取文本文件(44MB)并观察/ proc / pid / smaps。我发现尚未释放的内存在堆中成为Private_Dirty。
00fb3000-04643000 rw-p 00000000 00:00 0 [heap]
Size: 55872 kB
Rss: 55844 kB
Pss: 55163 kB
Shared_Clean: 0 kB
Shared_Dirty: 1024 kB
Private_Clean: 0 kB
Private_Dirty: 54820 kB
Referenced: 54972 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
答案 0 :(得分:1)
Python的垃圾收集器会在不再引用时删除对象。只要写入速率能够跟上存储硬件的读取速率,就必须能够在不增加内存和占用内存的情况下从两个独立的线程/进程同时写入文件内容来读取文件的内容。我相信当您使用更适合您的用例的Python语言结构时,您的问题就会消失。我会尝试对此发表评论。
要逐行读取文件,您应该使用以下概念:
with open('filepath') as f:
for line in f:
do_something_with(line)
您不必明确.close()
该文件。这同样适用于编写文件。在此处阅读with
语句:http://effbot.org/zone/python-with-statement.htm
从我的观点来看,对于您提供的用例,multiprocessing.Pipe
而不是multiprocessing.Queue
因为“类似流”的应用程序而更合适。将原始文件内容表示为队列中的项目似乎很奇怪。此外,如果您使用线程而不是独立的子进程(那么您应该使用os.pipe
进行线程间通信)**,您可以摆脱大量的通信开销。**。在任何情况下,启动后都应该join()
个线程和子进程。
**对于您的用例(复制文件),全局解释器锁(GIL)不会是性能问题。