Noté que mi aplicación Python es mucho más lenta cuando la python:2-alpine3.6
ejecuto sin Docker en Ubuntu. Se me ocurrieron dos pequeños comandos de referencia y hay una gran diferencia visible entre los dos sistemas operativos, tanto cuando los estoy ejecutando en un servidor Ubuntu como cuando estoy usando Docker para 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
También probé el siguiente 'punto de referencia', que no usa 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
¿Qué podría estar causando esta diferencia?
ubuntu
performance
docker
alpine-linux
Underyx
fuente
fuente
Respuestas:
Ejecuté el mismo punto de referencia que usted, usando solo Python 3:
resultando en más de 2 segundos de diferencia:
Alpine está utilizando una implementación diferente de
libc
(biblioteca del sistema base) del proyecto musl ( URL espejo ). Hay muchas diferencias entre esas bibliotecas . Como resultado, cada biblioteca podría funcionar mejor en ciertos casos de uso.Aquí hay una diferencia entre los comandos anteriores . La salida comienza a diferir de la línea 269. Por supuesto, hay diferentes direcciones en la memoria, pero por lo demás es muy similar. Obviamente, la mayor parte del tiempo se pasa esperando
python
a que termine el comando.Después de instalar
strace
en ambos contenedores, podemos obtener una traza más interesante (he reducido el número de iteraciones en el punto de referencia a 10).Por ejemplo,
glibc
está cargando bibliotecas de la siguiente manera (línea 182):El mismo código en
musl
:No digo que esta sea la diferencia clave, pero reducir la cantidad de operaciones de E / S en las bibliotecas principales podría contribuir a un mejor rendimiento. Desde el diff puede ver que ejecutar el mismo código de Python puede conducir a llamadas de sistema ligeramente diferentes. Probablemente lo más importante se podría hacer para optimizar el rendimiento del bucle. No estoy lo suficientemente calificado para juzgar si el problema de rendimiento es causado por la asignación de memoria o alguna otra instrucción.
glibc
con 10 iteraciones:musl
con 10 iteraciones:musl
es más lento en 0.0028254222124814987 segundos. A medida que la diferencia aumenta con el número de iteraciones, supongo que la diferencia está en la asignación de memoria de los objetos JSON.Si reducimos el punto de referencia a solo importar
json
, notamos que la diferencia no es tan grande:La carga de las bibliotecas de Python parece comparable. Generar
list()
produce una mayor diferencia:Obviamente, la operación más costosa es la
json.dumps()
que podría señalar diferencias en la asignación de memoria entre esas bibliotecas.Mirando nuevamente al punto de referencia , la
musl
asignación de memoria es realmente un poco más lenta:No estoy seguro de lo que se entiende por "gran asignación", pero
musl
es casi 2 veces más lento, lo que puede llegar a ser significativo cuando repite tales operaciones miles o millones de veces.fuente