Пишу одно приложеньице на Django и Grab'e. Оно отправляет ОЧЕНЬ много запросов серверам в интернетах и сохраняет спарсеные данные ответов в бд. Оригинальные данные обновляются на серверах почти непрерывно. Сейчас, на локальном сервере, весь экшн запускается по моей команде, но в продакшене я хочу сделать это непрерывным процессом (загрузил ответ, фоном спарсил, сохранил в базу, опять загружать и парсить пошел - никто и не заметил).
Вопрос в следующем:
Т.к. количество исходящих от меня http запросов просто зашкаливает, скорость работы однопоточного скрипта не очень радует.
Хотелось бы узнать, есть ли какой-то способ существенно ускорить мой скрипт? Я не очень хорошо разбираюсь в потоках, но подумал, что возможно есть способ делегировать им часть моих запросов... Ведь, если рассуждать логически, те сервера в интернете, куда я шлю столько запросов, получают их в сотни раз больше от разных пользователей, и успевают на все отвечать. Да, у них лучше железо и шире канал связи, но только ли в этом дело?
P.S. Если Вы, возможно, не поняли мой вопрос или считаете, что данную тему невозможно раскрыть в рамках Тостера, посоветуйте книжку, где объясняется, как вот такие непростые web-сервисы строить.
много потоков это хорошо, но с ростом количества потоков производительность будет падать ну то есть 8 потоков будут работать не в два раза быстрее чем 4.
У вас по сути большая часть времени - это работа с сетью, что медленно. Выход - event loop. В рамках одного потока запускаем много много неблокируемых запроса, и по мере завершения запросов обрабатываем результат.
Комбинация нескольких потоков (по количеству ядер процессора) и event loop даст максимальную утилизацию процессора.
Олег Цилюрик: вы про то что потоки в python это ни что иное как мультиплексирование выполнения нескольких потоков управления без реальной паралелизации? Насколько я помню можно все же настоящие треды использовать в python и да, при таком раскладе 8 потоков будут быстрее чем 1 но не в 8 раз.
Ну и да, я пожалуй имел в виду процессы отдельные что бы не отбирать для event loop лимит в количество хэндлеров сокетов на процесс.
Я не очень хорошо разбираюсь в потоках, но подумал, что возможно есть способ делегировать им часть моих запросов...
Много потоков в Python - это фикция ... за счёт GIT.
В Python исполнение в несколько потоков не ускоряет, а замедляет итоговое выполнение программы ... что бы вам тут не дудели умники.
Александр Мелеховец:
А что вы хотите услышать? Что вы тестируете глупость?
... ну, пожалуйста: вы тестируете время выполнения блокирующих операций HTTP GET.
Олег Цилюрик: именно так. Собственно, в своих статьях, которые рекомендуете выше, вы также говорите, что многопоточность в питоне уместна для задач, в которых большую часть времени выполнения занимают блокирующие вызовы. Однако в ответах вы снова не отделяете этот случай и утверждаете, что многопоточность в питоне ВСЕГДА тормозит :)
Если серьёзно, я просто пытаюсь понять, почему вы так делаете. Сознательно упрощаете, чтобы не пускаться в пространные объяснения, почему оно так и как отличить одно от другого? Придираетесь к терминологии исполнение/ожидание, поток ОС/поток управления? Что-то другое? Объясните пожалуйста, и я от вас отстану :)
Стараюсь иногда, не вдаваясь в разъяснения, кратко поставить обсуждение в парадоксальное положение, которое заставит думать самостоятельно...
Может, и не всегда удачно.
Сознательно упрощаете, чтобы не пускаться в пространные объяснения, почему оно так и как отличить одно от другого?
Там, где нужно параллельно выполнять блокирующие операции, неуместны параллельные потоки, достаточно какой-то очереди выполнения, что-то типа select() в POSIX.
По крайней мере, если операции - пассивное ожидание, то там бессмысленно рассуждать о увеличении производительности выполнения, потому что там нет выполнения.
Хотелось бы узнать, есть ли какой-то способ существенно ускорить мой скрипт?
Попробуйте для запросов в сеть использовать aiohttp. Это библиотека на основе событийного цикла про который писал Сергей Протько . Будет ли ускорение радикальным не знаю, но то что оно будет уверен почти на 100%.