Найти - Пользователи
Полная версия: httplib2 низкая результативность при увеличении потоков.
Начало » Python для новичков » httplib2 низкая результативность при увеличении потоков.
1 2 3 4
DHT
В многопоточной программе исользуются очереди и httplib2.
Прога делает GET запрос по списку URL и проверяет вхождение фразы в ответе сервера.

Странность:
В 1 поток работает со скоростью 0,8 адресов в секунду.
В 5 потоков - 4,3 адреса в секунду.
В 20 потоков - 5,1 адреса в секунду.
В 50 потоков - 12,8 адреса в секунду.

Т.е. рост числа потоков не приводит к пропорциональному росту производительности.
При этом:
- у каждого потока есть задание в нужный момент времени, т.е. он не простаивает и с увеличеним числа потоков растет время выполнения кода:
httplib2.request(url, 'GET', headers=headers)
- нагрузка на процессор меньше 10%;
- канал 100мбит/с загружен меньше, чем на 1%.

Находил, что в старых версиях httplib2 было: http://code.google.com/p/httplib2/issues/detail?id=91
что решилось вводом
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

Как понять что сейчас (внутри библиотеки httplib2) тормозит процесс?
Lexander
Соединение используется одно и то же или в каждом потоке свое?
Может быть сервер все же тормозит по какой-то причине?
Нужно больше кода.
DHT
Соединение используется одно и то же или в каждом потоке свое?
Свое. Т.е. каждый поток может работать и через отдельный прокси сервер.

Lexander
Может быть сервер все же тормозит по какой-то причине?
Проверял скорость канала через сервисы TestMySpeed, SpeedTests и т.п.
Также запускал схожий софт на Delphi, который в 200 потоков работал в раз 100-150 быстрее, чем в 1 поток, т.е. подобной проблемы на наблюдалось.

Главный поток (выдержка):
self.queue_input = Queue.Queue(100)
self.queue_output = Queue.Queue()
...
while True:
    # обработка очереди результатов
    while not self.queue_output.empty():
        q = self.queue_output.get_nowait()
        ....
    # обновление очереди заданий
    if not self.queue_input.full():
        while not self.queue_input.full():
            self.queue_input.put_nowait(q)
            ...

Дополнительные потоки (выдержка):
rl = threading.RLock()
while True:
    # взять новое задание из очереди заданий
    with rl:
        self.q = self.p.queue_input.get_nowait()
    # выполнить задние
    self.h = httplib2.Http()
    self.h.timeout = 30
    (response, content) = self.h.request(url, 'GET', headers=headers)
    # записать результат в очередь результатов
    with rl:
        self.p.queue_output.put_nowait(self.q)
JOHN_16
DHT
В качестве альтернативного подхода воспользуйтесь идеями примеров Здесь. У меня с ftp коннектами было ожидаемое увеличение производительности.
Или попробуйте другую библиотеку (можно ниже уровнем т.е. на сокетах , так как сама задача у вас несложная судя по всему)
DHT
JOHN_16,
Если вместо запроса по HTTP сделать какое-нибудь простое дейтсвие, то потоки отрабатывают 10ки тысяч записей из очереди в секунду. Т.е. на реализацию работы с очередями я не жалуюсь. Жалусь лишь на httplib2.

JOHN_16
Или попробуйте другую библиотеку (можно ниже уровнем т.е. на сокетах , так как сама задача у вас несложная судя по всему)
Вот этого бы совсем не хотелось. Т.к. именно для httplib2 написал уже очень много чего хорошего: куки менеджер, multipart/form-data и другое. Хотелось бы разрешить пробему, т.к. по ссылке http://code.google.com/p/httplib2/issues/detail?id=91 пишут, что в старой версии поднимали производительность до 2500 одновременных соединений.
DHT
Что-то httplib и urllib2 дают такие жи плачевные результаты. Списать на GIL?
p.s. Python 2.7
Soteric
Какая операционная система и сколько ядер на сервере?
DHT
Сервер слабенький. Одноядерный с Windows Server 2003
Soteric
Хорошо бы профилировщиком посмотреть на что тратится время, но я к сожалению не силен в профилировании питон приложений.
DHT
Спасибо за наводку. Возможно, что и поможет найти узкие места.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB