Я заметил, что мое приложение на Python работает намного медленнее, python:2-alpine3.6
чем без Docker в Ubuntu. Я предложил две небольшие команды тестирования, и между двумя операционными системами заметна огромная разница, как при запуске их на сервере Ubuntu, так и при использовании Docker для Mac.
$ BENCHMARK="import timeit; print(timeit.timeit('import json; json.dumps(list(range(10000)))', number=5000))"
$ docker run python:2-alpine3.6 python -c $BENCHMARK
7.6094589233
$ docker run python:2-slim python -c $BENCHMARK
4.3410820961
$ docker run python:3-alpine3.6 python -c $BENCHMARK
7.0276606959
$ docker run python:3-slim python -c $BENCHMARK
5.6621271420
Я также попробовал следующий «бенчмарк», который не использует Python:
$ docker run -ti ubuntu bash
root@6b633e9197cc:/# time $(i=0; while (( i < 9999999 )); do (( i ++
)); done)
real 0m39.053s
user 0m39.050s
sys 0m0.000s
$ docker run -ti alpine sh
/ # apk add --no-cache bash > /dev/null
/ # bash
bash-4.3# time $(i=0; while (( i < 9999999 )); do (( i ++ )); done)
real 1m4.277s
user 1m4.290s
sys 0m0.000s
Что может быть причиной этой разницы?
ubuntu
performance
docker
alpine-linux
Underyx
источник
источник
Ответы:
Я выполнил тот же тест, что и вы, используя только Python 3:
в результате разница более 2 секунд:
Alpine использует реализацию
libc
(базовую системную библиотеку), отличную от проекта musl ( зеркальный URL ). Есть много различий между этими библиотеками . В результате каждая библиотека может работать лучше в определенных случаях использования.Вот разница между этими командами выше . Вывод начинает отличаться от строки 269. Конечно, в памяти есть разные адреса, но в остальном он очень похож. Большая часть времени, очевидно, тратится на ожидание
python
команды.После установки
strace
в оба контейнера мы можем получить более интересную трассировку (я сократил количество итераций в тесте до 10).Например,
glibc
загружает библиотеки следующим образом (строка 182):Тот же код в
musl
:Я не говорю, что это ключевое отличие, но сокращение числа операций ввода-вывода в основных библиотеках может повысить производительность. Из сравнения видно, что выполнение одного и того же кода Python может привести к немного другим системным вызовам. Вероятно, самое важное можно сделать при оптимизации производительности цикла. Я недостаточно квалифицирован, чтобы судить, вызвана ли проблема производительности выделением памяти или какой-либо другой инструкцией.
glibc
с 10 итерациями:musl
с 10 итерациями:musl
медленнее на 0,0028254222124814987 секунд. Поскольку различие увеличивается с увеличением количества итераций, я предполагаю, что разница заключается в распределении памяти для объектов JSON.Если мы сократим эталонный тест исключительно до импорта,
json
мы заметим, что разница не так уж велика:Загрузка библиотек Python выглядит сопоставимо. Генерация
list()
производит большую разницу:Очевидно, что наиболее дорогой является операция
json.dumps()
, которая может указывать на различия в распределении памяти между этими библиотеками.Еще раз посмотрим на эталонный тест ,
musl
который немного медленнее распределяет память:Я не уверен, что подразумевается под «большим распределением», но
musl
он почти в 2 раза медленнее, что может стать значительным, если вы повторяете такие операции тысячи или миллионы раз.источник