Python:睡眠线程的惩罚

时间:2010-02-01 17:09:20

标签: python performance multithreading

这个问题涉及在网络服务器上有大量睡眠python线程可能会或可能不会产生的性能损失。

背景:我正在使用django / satchmo实现在线商店。要求延迟付款。客户可以预订产品并允许第三方在以后付款(通过随机且唯一的URL)。

要处理未保留的项目,我将创建一个线程,该线程将在预订时间内休眠,然后删除预订/标记产品在醒来时销售。它看起来像这样:

#Reserves a product when it is placed in the cart
def reserve_cart_product(product):
  log.debug("Reserving %s" % product.name)
  product.active = False
  product.featured = False
  product.save()
  from threading import Timer
  Timer(CART_RESERVE_TIME, check_reservation, (product,)).start()

我在使用过期后剔除唯一网址时使用相同的技术,只有计时器休眠的时间更长(通常为5天)。

所以,我问你的问题如下:

是否有大量的睡眠线会严重影响性能?是否有更好的技术可以在将来的某个时间安排一次性事件。如果可能的话,我想在python中保留它;没有通过at致电cronsys

该网站的流量并不高;每周订购产品的(慷慨)上限约为100.结合购物车预订,这可能意味着任何时候都有100多个睡眠线程。我会后悔以这种方式安排任务吗?

由于

3 个答案:

答案 0 :(得分:7)

我认为没有理由不这样做。 Timer的底层代码(在threading.py中)只使用time.sleep。一旦它等待一段时间,它基本上会运行一个带有time.sleep(0.05)的循环。这应该导致CPU使用率基本上为0%,即使有数百个线程。这是一个简单的例子,我注意到python进程的0%cpu使用率:

import threading

def nothing():
    pass

def testThreads():
    timers = [threading.Timer(10.0, nothing) for _ in xrange(881)]
    print "Starting threads."
    map(threading.Thread.start, timers)
    print "Joining threads."
    map(threading.Thread.join, timers)
    print "Done."

if __name__ == "__main__":
    testThreads()

真正的问题是你可能无法真正启动太多线程。在我的64位4GB系统上,我只能在出现错误之前启动881个线程。但是,如果你真的只有几百个,我无法想象它会起作用。

答案 1 :(得分:4)

100个线程没问题,但是tgray pointed out,如果服务器出现故障会发生什么(断电,计划维护,硬件故障等)?

您需要将保留信息存储在您的数据库中。

然后你可以让一个cron作业定期触发一个unservation脚本,例如,你不需要让所有这些线程都坐在那里。

如果你真的不想使用cron,只需要让一个工作线程休眠一分钟,然后检查是否有任何遗漏。

答案 2 :(得分:3)

通常,休眠线程除了为其堆栈和其他私有数据分配的内存之外没有其他开销。现代操作系统调度算法具有复杂度O(1),因此即使正在运行的线程也不会引入开销,而不是内存占用。 同时,很难想象有效的设计需要大量的线程。只有我能想象的情况是与许多其他同行的沟通。在这种情况下 - 应该使用异步IO。