Как стать автором
Обновить

Комментарии 34

Не… на win7 x64 не работает :)
Вчера тестил, работало в обоих вариантах. На что ругается?
На функцию __search_so
        for file in os.listdir(dir):
            if file.startswith(name):
                res.append( os.path.join(dir, file) )

WindowsError: [Error 3]: '/lib/*.*'
Исправлено, выложено на GIT, ответил в личку.
А как влияет affinity на ту часть кода потока, которая выполняется в режиме ядра? В частности, что на счет параллельных IO операций?
Поток также останавливается на время I/O. Никаких отличий, мы просто запрещаем системе выполнять наш код на других ядрах.
Посмотрите на календарь =)
Самый оригинальный рецепт работы с GIL, который я видел.
Исходыне данные:
12.909442544
17.7961015701


Дописали в начало файла:
from gevent import monkey; monkey.patch_all()

Получили результат:
12.9433840513
12.8199769258


Заменили в коде два слова Thread на два слова Process, получили результат:
12.8545324802
6.45484101772


Вывод: по-моему автор пытается копать землю мотыгой, и вместо того, чтобы сменить мотыгу на лопату — он изобретает нейромотыгокопатель, который по-прежнему хуже, сложнее и менее надежен лопаты, но зато своего собственного производства.
Ах черт… первое апреля… Простите
Одна из причин, почему мы начали отказываться от питона в продакте.

Почему-то все, кто говорит про GIL говорят «ну если у вас там зубодробительная математика, то»…

А на самом деле проблема проще: если у вас сервер, то у вас есть очень серьёзная проблема при росте нагрузки. Даже если на каждый запрос уходит 1мс, как только к вам придёт 2000 запросов за секунду, у вас начинаются лаги. Хоть у вас там и 20 ядер в запасе.
На 20 ядрах вполне нормально работают 100 процессов.
Вы говорите про процессы. А сколько тредов одного питона будут нормально работать? Сразу отвечаю на пример задачи, которая процессами трудно реализуется.

Предположим, у вас есть in-memory хранилище данных. Например, список объектов. Клиенты получают к ним доступ, что-то делают, отключаются. Частота обращений очень высокая, объём работы — маленький. В этом случае резать его на процессы — это выносить хранение в in-memory db (отдельным процессом), что сильно оверхед и иногда слишком медленно. Если же делать тредами и общими объектами — привет GIL'у.
Вы shared memory не рассматриваете в принципе?
Рассматривали в своё время. Оказалось настолько неудобно, что было проще реализовать pipe-подобный интерфейс между компонентами.

Повторю, на python можно писать. Но как только речь заходит о росте нагрузок, как тут же выясняется, что нужно капитально напрягаться и придумывать архитектуру, нацеленную на борьбу с GIL.
Мой опыт подсказывает, что разработка высоконагруженных сервисов сильно отличается от «просто скриптиков». Так или иначе приходится хорошо думать, решая одновременно целый комплекс задач. Наличие или отсутствие GIL уже не играет большой роли — так, штришок к общим требованиям и ни разу не основное препятствие к прекрасному будущему.
Давайте скажем так, есть _ВЫСОКО_ нагруженные (условно говоря, мы выходим на уровень, когда возникает желание размазать сервис по нескольких серверам), а есть просто нагруженные — когда сервис вполне может уживаться в уголке сервера и не вякать. Казалось бы, в чём проблема? Но питоновское «не вякать» заканчивается раньше, чем хотелось.

Грубый пример. У нас есть обработчик консолей на хосте виртуализации. Средняя плотность — 20-100 машин на хост. Обработать 100 потоков по 64к — это высокая нагрузка или нет? Питон с такой нагрузкой справляется с большим трудом.
На чом в результате реализованили «100 потоков по 64к»? Не тролинга ради, а инфрормации для. Просто у меня сейчас у самого подобная задача есть, порядко тысячи постоянных медленных конектов обрабатывать, собирается статистика с специфичных устройств, объемы маленькие, но данные идут постонянно. Поделитесь идеями пожалуйста.
Одна часть всё ещё на питоне (подлагивает иногда, но терпим). Часть, которая в мир смотрит (и запросы клиентов обслуживает) — хаскел.
хаскел в продакте!?
вы не шутите?
Смотрите наш блог (http://habrahabr.ru/company/selectel/). В настоящий момент у нас несколько компонент уже переписаны и работают (с моей точки зрения) замечательно (то есть я не замечаю их сущетсвования и уверенно пользуюсь результатами их работы).
поток в 64k — что имеется в виду?
Скорость потока принято измерять в килобайтах в секунду или килобитах в ту же секунду.

Если речь идет о виртуальных машинах — то собственная связность этих потоков очень небольшая. В результате все отлично должно раскладываться по процессам. Нет?
128*64=8192 бит/с
Ничего не понял
Пардон, 8192 кбит/с
Значит, имеем по 64КБит/сек от виртуалки. Предполагаю, что обработка этого потока делается почти независимо от остальных. Вас может интересовать периодическое обновление статистики, биллинга и обратный контроль над виртуалкой. Итого имеем звезду, в которой главный процесс управляет оркестром а работники (несколько штук) работают с потоками данных и т.д.
Получаем изолированность, масштабируемость и бОльшую надежность. Проблема GIL решается автоматически.
Так на хайлоаде обычно используется корпоративная многозадачности — tornado, twisted, gevent и другие, работающие через epoll. Т.е. запускается по 1 треду на ядро, а дальше работает по тому же принципу, по которому и nginx — никаких тредов.

Производительность получается более чем достаточная для 2000 запросов в секунду, и GIL тут не помеха.
Не «корпоративная», а «кооперативная», это раз. С gevent'ом мы работаем, но на него много нареканий. Все не назову, нужно программистов внимательно выслушивать.

Проблема «кооперативной многозадачности» состоит в том, что там лимит производительности — 100% CPU.
Спасибо за поправку, это да, я что-то совсем заговорился. Но ведь можно запустить по 1 процессу на ядро. Twisted и tornado по-моему делают это из коробки, по крайней мере второй точно делал. И тогда будет лимит — 100% всех ядер CPU, как и для любой другой программы или языка.
Не имеет значения, каким образом обеспечивается работа гринлетов (у них могут быть и другие названия). Проблема состоит в том, что получается 100% CPU (за вычетом IO), которые могут иметь общие объекты. Хочешь больше — начинай танцевать вокруг IPC или надейся на то, что GIL до какого-то предела выдаст больше 100% CPU (это действительно так, за счёт вызовов библиотек). А хочется иметь если не линейную, то хотя бы идущую вверх кривую производительности по мере роста числа ядер.
Поясните, возможно я вас неверно понял: речь идет про 100% ядра или 100% всех ядер CPU?

Если первое, то чем плох способ пультипроцессинг (не мультитреадинг), по количеству ядер, поверх которого натягивается асинхронное IO?
Если второе, то каким образом другой язык может задействовать более 100% вычислительной мощности железа?
Просто не далее чем неделю назад я общался с ведущим программистом компании, которая держит самую популярную игру ВКонтакте (≥9,1 млн пользователей), и разрабатывает другие игры. Так вот бэкенд у них пишется на python/tornado/nosql. При этом нагрузка далеко переваливает за 100 и 1000 одновременных процессов/потоков.

Возможно, это другой класс задач, нежели ваш. Однако это тоже хайлоад. Хочется понять под какой круг задач подходит инструмент, а под какой нет. И чем плоха кооперативная модель в Вашем случае.
Если tornado процессы между собой «общаются» только через NoSQL хранилище — то тут вопросов нет.
Если им нужно нечто большее, то, видимо, в гости приходят костыли и проблемы.

Я лично не сталкивался с нагрузкой более 20-30 запросов в секунду, но такую нагрузку отлично держит и один python-процесс (работа не cpu-bound).
Можно синхронизовать внешне, ну или правда танцевать с IPC и/или multiprocessing.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории