我正在编写一个Python程序,以便从本地文件系统读取110000+文本文件并将其推送到MongoDB中。这是我的代码片段。
EmailProducer类(threading.Thread):
def __init__(self, threadID, queue, path):
self.threadID = threadID
self.queue = queue
self.path = path
threading.Thread.__init__(self)
def run(self):
if (queue.empty()):
files = os.listdir(self.path)
print(len(files))
for file in files:
queue.put(file)
EmailConsumer类(threading.Thread):
def __init__(self, threadID, queue, path, mongoConn):
self.threadID = threadID
self.queue = queue
self.mongoConn = mongoConn
self.path = path
threading.Thread.__init__(self)
def run(self):
while (True):
if (queue.empty()):
mongoConn.close()
break
file = queue.get()
self.mongoConn.persist(self.path, file)
EmailProducer实例从本地文件系统读取文件,如果队列为空,则将它们存储在队列中;EmailConsumer实例从队列中获取文件,并将它们推入Mongo.我还写了一个相同功能的顺序版本。我在我的ubuntu 12.04 32位台式机和i-5四核处理器上运行这两个系统,并对它们进行了计时。多线程版本从1个生产者和7个消费者开始。然而,它们都花费了大约23.7秒的实时时间和21.7秒的用户时间。我认为线程在这里会有帮助,但数字告诉我它没有帮助。
有人对这个原因有什么深刻的想法吗?
发布于 2012-04-06 01:37:26
线程化对于IO受限的操作并不是很有用。尤其是在全局解释器锁的情况下。所以一次只有一个线程在运行。我很惊讶在没有线程的情况下它不会更快。看看如何使用select module或第三方库异步读取文件。
发布于 2012-04-06 01:43:04
Python线程化在某种程度上受到CPython中的is considered to be pretty poor in terms of performance的Global Interpreter Lock的限制,这可能会对您的结果做出贡献。
所有的C级扩展也需要specific GIL support to avoid "defeating threads",在阻塞外部资源的同时保持GIL。这意味着如果你正在使用一个C层库,例如,与MongoDB对话,它可能会在操作时阻塞其他线程。(我不知道它会不会--只知道它可能会。)
https://stackoverflow.com/questions/10038178
复制