Параллельная установка

Наш проект Django становится огромным. У нас есть сотни приложений и использование тонны сторонних пакетов python, многие из которых требуют компиляции C. Наши развертывания занимают много времени, когда нам нужно создать новую виртуальную среду для основных выпусков. С учетом сказанного, я хочу ускорить процесс, начиная с Пипа. Кто-нибудь знает о вилке Pip, которая будет устанавливать пакеты параллельно?

Шаги, которые я сделал до сих пор:

  • Я искал проект, который делает это с небольшим успехом. Я нашел этот Github Gist: https://gist.github.com/1971720, но результаты почти точно такие же, как у нашего однопоточного друга.

  • Затем я нашел проект Pip на Github и начал просматривать сеть вилок, чтобы узнать, могу ли я найти какие-либо коммиты, которые упомянули о том, что я делаю. Там беспорядок. Я разблокирую его и попытаюсь распараллелить его сам, если придется, я просто хочу, чтобы не тратить время на это.

  • Я видел разговор в DjangoCon 2011 от ep.io, объясняющий их материал для развертывания, и они упоминают о параллелизации pip, отправляя файлы .so вместо компиляции C и зеркалирования Pypi, но они не касались того, как они это сделали или что они использовали.

5 Solutions collect form web for “Параллельная установка”

Проанализировали ли вы процесс развертывания, чтобы узнать, где действительно идет время? Меня удивляет, что запуск нескольких параллельных процессов pip не ускоряет его.

Если пришло время запросить PyPI и найти пакеты (в частности, когда вы также загружаете из Github и других источников), может быть полезно настроить собственный PyPI. Вы можете разместить PyPI самостоятельно и добавить в свой файл requirements.txt ( docs ) следующее:

 --extra-index-url YOUR_URL_HERE 

или следующее, если вы хотите заменить официальный PyPI в целом:

 --index-url YOUR_URL_HERE 

Это может ускорить время загрузки, так как все пакеты теперь находятся на ближайшей машине.

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

Основываясь на ответе Джеймисона Беккера, следующий код выполняет параллельную загрузку Pip, а затем быстро устанавливает пакеты.

Сначала мы загружаем пакеты параллельно в каталог (dist). Это легко запускается параллельно без конфликтов. Каждое отпечатанное имя пакета распечатывается перед загрузкой, что помогает при отладке. Для получения дополнительной помощи измените -P9 на -P1 , чтобы загрузить последовательно.

После загрузки следующая команда сообщает Pip об установке / обновлении пакетов. Файлы не загружаются, они извлекаются из быстрого локального каталога.

Он совместим с текущей версией Pip 1.7, также с Pip 1.5.

Чтобы установить только подмножество пакетов, замените оператор `cat require.txt 'своей пользовательской командой, например' egrep -v github require.txt '

 cat requirements.txt | xargs -t -n1 -P9 pip install -q --download ./dist pip install --no-index --find-links=./dist -r ./requirements.txt 

Параллельная установка

В этом примере используется xargs для параллелизации процесса сборки примерно на 4 раза. Вы можете увеличить коэффициент параллелизации с max-procs ниже (держите его приблизительно равным количеству ваших ядер).

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

Загружайте и устанавливайте пакеты параллельно, по четыре за раз:

 xargs --max-args=1 --max-procs=4 sudo pip install < requires.txt 

Примечание. Xargs имеет разные имена параметров в разных дистрибутивах Linux. Проверьте справочную страницу вашего дистрибутива на предмет специфики.

То же самое, что указано в документе here-doc:

  cat << EOF | xargs --max-args=1 --max-procs=4 sudo pip install awscli bottle paste boto wheel twine markdown python-slugify python-bcrypt arrow redis psutil requests requests-aws EOF 

Предупреждение: существует вероятность того, что скорость этого метода может сбить содержимое пакетов (в зависимости от вашего дистрибутива), если несколько пипов попытаются установить одну и ту же зависимость в одно и то же время, но очень маловероятно, если вы делаете только 4 на время. Это может быть довольно легко исправлено командой pip install --uninstall depname .

Помог ли он, если вы создали свою систему сборки (например, Jenkins) и установите все в каталог виртуальной среды для конкретной сборки? Когда сборка завершается успешно, вы делаете виртуальную среду перемещаемой, архивируете ее и выталкиваете полученный tablall в хранилище «выпущенных архивов». Во время развертывания вам нужно взять последний архив и распаковать его на целевом хосте, а затем он должен быть готов к выполнению. Таким образом, если загрузка архива и загрузка займет около 2 секунд, чтобы распаковать его на целевом хосте, ваше развертывание займет 2,5 секунды.

Преимущество такого подхода заключается в том, что все установки пакетов происходят во время сборки, а не во время развертывания.

Caveat: ваш системный рабочий, который строит / компилирует / устанавливает вещи в виртуальный env, должен использовать ту же архитектуру, что и целевое оборудование. Кроме того, ваша система подготовки к выпуску продуктов должна будет заботиться о различных зависимостях библиотеки C, которые могут иметь некоторые пакеты Python (например, PIL требует, чтобы libjpeg установлен до того, как он сможет скомпилировать код, связанный с JPEG, также ситуация сломается, если libjpeg не установлен на целевой коробка)

Это хорошо работает для нас.

Создание виртуального env resocatable:

virtualenv --relocatable /build/output/dir/build-1123423

В этом примере build-1123423 представляет собой виртуальный виртуальный каталог env для сборки.

Вдохновленный ответом Джеймисона Беккера , я модифицировал скрипт установки, чтобы выполнить параллельные установки папок, и это похоже на улучшение. Мой скрипт bash теперь содержит фрагмент, подобный этому:

 requirements=''\ 'numpy '\ 'scipy '\ 'Pillow '\ 'feedgenerator '\ 'jinja2 '\ 'docutils '\ 'argparse '\ 'pygments '\ 'Typogrify '\ 'Markdown '\ 'jsonschema '\ 'pyzmq '\ 'terminado '\ 'pandas '\ 'spyder '\ 'matplotlib '\ 'statlab '\ 'ipython[all]>=3 '\ 'ipdb '\ ''tornado>=4' '\ 'simplepam '\ 'sqlalchemy '\ 'requests '\ 'Flask '\ 'autopep8 '\ 'python-dateutil '\ 'pylibmc '\ 'newrelic '\ 'markdown '\ 'elasticsearch '\ "'"'docker-py==1.1.0'"'"' '\ "'"'pycurl==7.19.5'"'"' '\ "'"'futures==2.2.0'"'"' '\ "'"'pytz==2014.7'"'"' ' echo requirements=${requirements} for i in ${requirements}; do ( pip install $i > /tmp/$i.out 2>&1 & ); done 

Я могу хотя бы искать проблемы вручную.

Python - лучший язык программирования в мире.