【问题标题】:Gevent queue high CPU usageGevent队列高CPU使用率
【发布时间】:2013-05-19 22:29:03
【问题描述】:

为什么这段代码会永久占用 95% 的 CPU? Producer 没有发送任何请求,但是 cpu 很热。如何在消费者 greenlet 中不添加显式非零睡眠超时的情况下降低 CPU 使用率?

from gevent import queue
from gevent import sleep
from gevent import Greenlet

def cons(q):
    while True:
        try:
            data = q.get_nowait()
        except queue.Empty:
            sleep(0)
            continue
        print data

def prod(q):
    while True:
        #q.put_nowait('hello')
        sleep(1)


if __name__ == '__main__':

    q = queue.Queue()
    cons1 = Greenlet.spawn(cons, q)
    prod1 = Greenlet.spawn(prod, q)
    cons1.join()
    prod1.join()

【问题讨论】:

    标签: python queue gevent


    【解决方案1】:

    在第 8 行,使用 get() 代替 get_nowait()

    data = q.get()
    

    超级简单,现在你的消费者会在等待更多工作时阻塞。

    【讨论】:

    • 这很好,但如果我有多个队列(例如控制和数据通道),这是一个糟糕的解决方案。我只是添加了 sleep(0.00001) 作为解决方法 - CPU 负载 3% 而不是 96。
    • @echo12345 不要使用sleepget 方法有一个timeout 参数:q.get(timeout=0.001)
    • 我很确定您不应该使用 get_nowait() 或超时参数。如果您阅读了多个队列,则只需制作多个 greenlet。与线程不同,greenlet 的创建和拆卸成本很低(可能数量很大)。
    【解决方案2】:

    所有推荐的最佳解决方案: 在每个队列的单独 greenlets 中使用 queue.get 阻塞调用。

    代码的下一部分轮询两个 gevent.queue 队列 + greenlet 内的 zmq.green 套接字 gr​​eenlet =) CPU 负载接近于零!

    def _zmq_poll(self):
        while True:
            sockets = super(Core, self)._zmq_poll()
            if sockets:
                if sockets.get(self.z_ctr) == zmq.POLLIN:
                    self.ctr_process()
    
    def ctr_process(self):
        self.send_log('new CTR: %s')
    
    def req_process(self):
        while True:
            req = self.q_req_core.get()
            self.send_log('new req: %s' % req)
            self.q_core_wrk.put(req)
    
    def wrk_process(self):
        while True:
            wrk_result = self.q_wrk_core.get()
            self.send_log('new result: %s' % wrk_result)
            self.q_core_res.put(wrk_result)
            self.test_wrk_result(wrk_result)
    
    def _run(self):
        self.slaves_start()
        req_process = Greenlet(self.req_process)
        wrk_process = Greenlet(self.wrk_process)
        zmq_poll = Greenlet(self._zmq_poll)
        req_process.start()
        wrk_process.start()
        zmq_poll.start()
        zmq_poll.join()
        req_process.join()
        wrk_process.join()
        self._cleanup()
    

    感谢您的建议!

    【讨论】:

      猜你喜欢
      • 2013-05-29
      • 2019-02-03
      • 2021-12-09
      • 2014-07-16
      • 2014-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多