【问题标题】:Python: penalty for sleeping threadsPython:对休眠线程的惩罚
【发布时间】:2010-02-01 17:09:20
【问题描述】:

这个问题与在网络服务器上拥有大量睡眠 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()

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

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

拥有大量休眠线程会严重影响性能吗?是否有更好的技术来安排未来某个时间的一次性活动。如果可能的话,我想把它保存在 python 中;请勿通过sys 致电atcron

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

谢谢

【问题讨论】:

  • 您可能需要一个比线程更持久的解决方案,以防您的服务器出现故障。据我所知,您必须搜索您的日志文件以了解崩溃后保留了哪些产品(尽管您不知道使用上述代码保留了多长时间)。
  • 你说得很好,正是出于这个原因,我开始在数据库中存储一些记录。
  • 您假设您的服务器不会重新启动,并且您不会收到数千个订单,对吧?更健壮的选择是持久数据库队列系统,例如 RabbitMQ。
  • @pisswillis,我遇到了完全相同的问题。我认为太多的睡眠线程会导致主要的性能问题。我会阅读答案,希望找到一个好的解决方案。
  • @pisswillis,不。看起来没有人相信这么多的睡眠线程(在我的情况下超过 300 个)开始引起问题。我会在互联网上搜索,希望能找到解决方案。

标签: python performance multithreading


【解决方案1】:

我看不出这不应该起作用的原因。 Timer 的底层代码(在 threading.py 中)只是使用 time.sleep。一旦它等待了一段时间,它基本上会运行一个带有 time.sleep(0.05) 的循环,这应该导致 CPU 使用率基本上为 0%,即使有数百个线程也是如此。这是一个简单的示例,我注意到 python 进程的 cpu 使用率为 0%:

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 个线程。但是,如果你真的只有几百个,我无法想象它不会起作用。

【讨论】:

    【解决方案2】:

    100个线程没问题,但是作为tgray pointed out,如果服务器宕机(断电、计划维护、硬件故障等)会怎样?

    您需要将取消预订信息存储在数据库中的某个位置。

    然后,您可以让 cron 作业定期触发取消预留脚本,而您不需要让所有这些线程闲置。

    如果您真的不想使用 cron,只需让一个工作线程休眠一分钟,然后检查是否有任何取消保留到期。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2010-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-10
        • 2011-09-18
        • 1970-01-01
        相关资源
        最近更新 更多