2016-04-10 1 views
3

Так я создаю переменную класса с именем исполнителя в моем классеЭтот стиль использования пула потоков с торнадо в порядке?

executor = ThreadPoolExecutor(100) 

и вместо того, чтобы функции и методы и использование декораторов, я просто использую следующую строку, чтобы обрабатывать мои блокирующие задачи (например, гипергликемии и создание хэш и .. ..) в моих методах асинхронного

result = await to_tornado_future(self.executor.submit(blocking_method, param1, param2) 

Я решил использовать этот стиль причины

1- декораторов медленнее по своей природе

2- нет необходимости в дополнительных методов и функций

3- это workes как ожидалось, и не создает темы, прежде чем он нужен

Я прав? Пожалуйста, используйте причины (я хочу знать, если путь я использую, медленнее или использует больше ресурсов или ....)

Update

основе Бен ответ мой выше подход не является правильным так Я закончил с использованием следующей функции по мере необходимости, я думаю, что это лучший способ пойти

def pool(pool_executor, fn, *args, **kwargs): 
    new_future = Future() 
    result_future = pool_executor.submit(fn, *args, **kwargs) 
    result_future.add_done_callback(lambda f: new_future.set_result(f.result())) 
    return new_future 

использование:

result = await pool(self.executor, time.sleep, 3) 

ответ

5

Это безопасно, если все ваши блокирующие методы являются потокобезопасными. Поскольку вы упомянули о выполнении IO в этих потоках, я укажу, что выполнение файла IO здесь прекрасное, но все сетевые IO в Tornado должны встречаться в потоке IOLoop.

Почему вы говорите, что «декораторы медленнее по своей природе»? Какие декораторы медленнее, чем что? У некоторых декораторов нет накладных расходов на производительность (хотя большинство из них имеют некоторую стоимость исполнения). to_tornado_future(executor.submit()) также не является бесплатным. (BTW, я думаю, вы хотите tornado.gen.convert_yielded вместо tornado.platform.asyncio.to_tornado_future. executor.submit не возвращает asyncio.Future).

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

+0

Я вижу ваш вопрос о to_tornado_future и executor.submit, но как я могу использовать executor.submit внутри выражения async def и ждать, чтобы получить результат? Я думаю, что невозможно использовать convert_yielded, я что-то упустил? – Mohammadhzp

+0

Хм, ты прав. 'convert_yielded' здесь не работает, но' to_tornado_future' делает. Возможно, специальная оболочка 'concurrent.futures.Future' в' convert_yielded' не стоит того. –

+0

Вы имеете в виду только сетевой ввод/вывод, который напрямую связан с Tornado, должен происходить в потоке 'IOLoop' или любом и любом сетевом вводе/выводе (например, с помощью' boto3')? Если последнее, почему? –