0

我正在编写一个 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。我还编写了相同功能的顺序版本。我在带有 i-5 四核处理器的 ubuntu 12.04 32 位台式机上同时运行它们,并对它们进行了计时。多线程版本从 1 个生产者和 7 个消费者开始。但是,它们都花费了大约 23.7 秒的实时时间和 21.7 秒的用户时间。我认为线程在这里会有所帮助,但数字告诉我它没有帮助。

任何人对原因有任何深刻的想法吗?

4

2 回答 2

3

线程对于 IO 绑定操作不是很有用。特别是没有全局解释器锁。所以一次只有一个线程在运行。我很惊讶没有线程它并没有更快。查看使用选择模块或第三方库异步读取文件。

于 2012-04-06T01:37:26.190 回答
0

Python 线程在某种程度上受到CPython 中的Global Interpreter Lock的限制,这被认为在性能方面非常差,并且可能有助于您的结果。

所有 C 级扩展还需要特定的 GIL 支持,以避免通过在阻塞外部资源的同时持有 GIL来“击败线程” 。这意味着如果您使用 C 层库来与 MongoDB 通信,则它可能会在运行时阻塞其他线程。(我不知道它是否确实如此 - 只是它可能。)

于 2012-04-06T01:43:03.860 回答