【问题标题】:Same socket speed is 66% slower on a new thread?相同的套接字速度在新线程上慢 66%?
【发布时间】:2017-10-03 08:15:23
【问题描述】:

这太疯狂了!我听说 Python 线程很慢,但这超出了正常范围。

这是伪代码:

class ReadThread:

    v = []
    def __init__(self, threaded = True):
        self.v = MySocket('127.0.0.1')
        if threaded:
            thread.start_new_thread(self._scan, ())

    def read(self):
        t0 = datetime.now()
        self.v.read('SomeVariable')
        t = datetime.now()
        dt = (t-t0).total_seconds()

        print dt

    def _scan(self):
        while True:
            self.read()

如果我在主线程的 while 循环中运行 read(),如下所示:

r = ReadThread(threaded = False)
while True:
    r.read()

dt 约为 78 毫秒,变化很小。现在,如果我在这样的新线程中运行它:

r = ReadThread(threaded = True)
while True:
    pass

dt 约为 130 毫秒,方差为 +-10 毫秒!

为什么这么慢?我做错了什么吗?只是在一个新线程中是一样的!

MySocket() 是一个使用套接字读取/写入变量到服务器的对象,而 read() 只是获取一些用于测试的变量。

【问题讨论】:

    标签: python multithreading performance sockets


    【解决方案1】:

    在不知道MySocket 是什么以及完整示例的情况下,很难在本地重现此问题。但是,我可以尝试猜测,问题在于这个循环:

    while True:
        pass
    

    这是非常 CPU消耗。 CPU 确实一直在运行,将 CPU 周期独占,而不是让套接字工作。

    相反,套接字读取操作通常是阻塞和空闲等待数据到达,因此它们几乎不消耗 CPU。

    在第一个示例中,您运行您的套接字,而没有其他东西占用 CPU。在第二个例子中,主线程完全消耗了 1 个 CPU。

    尝试用通常的空转操作替换此循环,例如time.sleep(60)。所以主线程会空闲60s,而socket线程会读取和处理数据。

    r = ReadThread(threaded = True)
    time.sleep(60)
    

    那么在这种情况下,衡量标准是什么?

    【讨论】:

    • 在实际代码中,每个线程通过写入列表来请求值。另一个线程读取列表并写下答案。它不断监视新请求。消费者线程不断监视响应。我发现一个小的 time.sleep() 可以解决问题,但是还有什么其他方法可以更好地解决问题?也许是事件?
    • 你应该学习线程同步原语(docs.python.org/3.4/library/threading.html)。我认为,Event 和/或 Condition 最适合您的用例,具体取决于需要响应的线程数。
    • Event 似乎非常适合请求数据的线程,它们也可以在请求中发送一个事件。我不确定如何唤醒使用套接字的线程。如果我有一个套接字线程的公共事件,那么 thread1 可以唤醒它,并且在它完成时 thread2 也试图唤醒它并失败。我可以使用锁,但我想确保请求按顺序进行。他们现在走了。我需要考虑一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2015-05-11
    • 2019-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多