2010-02-04 2 views
-1

Этот вопрос связан с другими, о которых я просил здесь, в основном относительно сортировки огромных наборов данных в памяти.Python: deferToThread XMLRPC Server - Twisted - Cherrypy?

В основном это то, что я хочу/у:

работает сервер Twisted XMLRPC. Этот сервер хранит несколько (32) экземпляров класса Foo в памяти. Каждый класс Foo содержит панель списка (которая будет содержать несколько миллионов записей). Существует служба, которая извлекает данные из базы данных и передает ее на сервер XMLRPC. Данные в основном словарь, с помощью клавиш, соответствующих каждому экземпляру Foo, а значения представляют собой список словарей, например, так:

data = {'foo1':[{'k1':'v1', 'k2':'v2'}, {'k1':'v1', 'k2':'v2'}], 'foo2':...} 

Каждый экземпляр Foo затем передается значение, соответствующее его ключ, и Foo. bar словари обновляются и сортируются.

class XMLRPCController(xmlrpc.XMLRPC): 

    def __init__(self): 
     ... 
     self.foos = {'foo1':Foo(), 'foo2':Foo(), 'foo3':Foo()} 
     ... 

    def update(self, data): 
     for k, v in data: 
      threads.deferToThread(self.foos[k].processData, v) 

    def getData(self, fookey): 
     # return first 10 records of specified Foo.bar 
     return self.foos[fookey].bar[0:10] 

class Foo(): 

    def __init__(self): 
     bar = [] 

    def processData(self, new_bar_data): 
     for record in new_bar_data: 
      # do processing, and add record, then sort 
      # BUNCH OF PROCESSING CODE 
      self.bar.sort(reverse=True) 

Проблема заключается в том, что, когда функция обновления вызываются в XMLRPCController с большим количеством записей (скажем, 100K +) он перестает отвечать на мой GetData вызовов, пока все 32 экземпляров Foo не завершат метод process_data. Я думал, что deferToThread будет работать, но я думаю, что я недопонимаю, где проблема.

Любые предложения ... Я открыт для использования чего-то другого, такого как Cherrypy, если он поддерживает это требуемое поведение.


EDIT

@Troy: Это как реактор установлен

reactor.listenTCP(port_no, server.Site(XMLRPCController) 
reactor.run() 

Насколько GIL, было бы жизнеспособным вариантом для изменения sys.setcheckinterval () значение для чего-то меньшего, поэтому блокировка данных отпущена, чтобы ее можно было прочитать?

ответ

1

Самый простой способ заставить приложение быть отзывчивым - это разбить интенсивную обработку процессора на меньшие куски, позволяя скрученному реактору работать между ними. Например, вызывая реактор.callLater (0, process_next_chunk) для перехода к следующему фрагменту. Эффективное выполнение совместной многозадачности самостоятельно.

Другим способом было бы использование отдельных процессов для выполнения работы, тогда вы выиграете от нескольких ядер. Взгляните на Ampoule: https://launchpad.net/ampoule Он предоставляет API, похожий на deferToThread.

+0

Включение каждого из экземпляров Foo в свой собственный дочерний процесс звучит как разумная вещь, чтобы попробовать, по крайней мере, для начала. –

0

Я не знаю, как долго проходит процесс processData, и как вы настраиваете свой скрученный реактор. By default, скрученный реактор имеет пул потоков от 0 до 10 нитей. Возможно, вы пытаетесь отложить до 32 длительных вычислений до целых 10 потоков. Это неоптимально.

Вы также должны спросить, какую роль играет GIL при обновлении всех этих коллекций.

Редактировать: Прежде чем вносить какие-либо серьезные изменения в вашу программу (например, вызывать sys.setcheckinterval()), вы должны запустить ее с помощью профилировщика или модуля трассировки python. Они должны сказать вам, какие методы используют все ваше время. Без правильной информации вы не можете внести правильные изменения.

Смежные вопросы