Python: штраф за спящие темы - PullRequest
7 голосов
/ 01 февраля 2010

этот вопрос относится к снижению производительности, которое может возникнуть или не возникнуть из-за наличия большого количества спящих потоков 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-адресов после истечения срока их действия, только таймер спит гораздо дольше (обычно 5 дней).

Итак, мой вопрос к вам так:

Будет ли большое количество спящих потоков серьезно влиять на производительность? Существуют ли лучшие методы для планирования одного события в будущем. Я хотел бы сохранить это в Python, если это возможно; без звонка at или cron через sys.

Сайт не очень высокий трафик; (щедрый) верхний предел для продуктов, заказанных в неделю, будет около 100. В сочетании с резервированием корзины, это может означать, что в любой момент времени может быть более 100 спящих потоков. Буду ли я сожалеть о планировании задач таким образом?

Спасибо

Ответы [ 3 ]

7 голосов
/ 01 февраля 2010

Я не вижу причин, почему это не должно работать.Базовый код для Timer (в threading.py) просто использует time.sleep.Как только он ждет некоторое время, он в основном запускает цикл с time.sleep (0,05). Это должно привести к тому, что загрузка ЦП составит в основном 0%, даже с сотнями потоков.Вот простой пример, где я заметил 0% использования процессора для процесса python:

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-битной системе 4 ГБ, я могу только запустить 881 поток, прежде чем я получу ошибку.Если у вас действительно будет всего несколько сотен, я не могу себе представить, что это не сработает.

4 голосов
/ 01 февраля 2010

100 потоков - это не проблема, но, как указал tgray , что произойдет, если сервер выйдет из строя (отключение питания, плановое обслуживание, аппаратный сбой и т. Д.)?

Вам нужно где-то хранить информацию о бронировании в вашей базе данных.

Затем вы можете периодически запускать задание cron, например, для задания cron, и вам не нужно, чтобы все эти потоки сидели без дела.

Если вы действительно не хотите использовать cron, просто создайте один рабочий поток, который спит минуту, а затем проверяет, не возникли ли какие-либо сомнения.

3 голосов
/ 01 февраля 2010

Обычно спящие потоки не имеют никаких накладных расходов, кроме памяти, выделенной для их стеков и других личных данных. Современные алгоритмы планирования операционной системы имеют сложность O (1), поэтому даже работающий поток не вносит накладных расходов, кроме объема памяти. В то же время сложно представить эффективный дизайн, требующий большого количества потоков. Единственный случай, который я могу себе представить, это общение со многими другими сверстниками. В этом случае следует использовать асинхронный ввод-вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...