我使用Python 3运行了与您相同的基准测试:
$ docker run python:3-alpine3.6 python --version
Python 3.6.2
$ docker run python:3-slim python --version
Python 3.6.2
导致超过2秒的差异:
$ docker run python:3-slim python -c "$BENCHMARK"
3.6475560404360294
$ docker run python:3-alpine3.6 python -c "$BENCHMARK"
5.834922112524509
Alpine正在使用libc
与musl项目(镜像URL)不同的(基本系统库)实现。这些库之间有很多区别。结果,每个库在某些用例中可能会表现更好。
这是上述命令之间的差异。输出与第269行开始有所不同。内存中当然有不同的地址,但除此之外非常相似。显然,大部分时间都花费在等待python
命令完成上。
将它们安装strace
到两个容器中之后,我们可以获得一个更有趣的跟踪(我将基准测试中的迭代次数减少到10个)。
例如,glibc
以下列方式加载库(第182行):
openat(AT_FDCWD, "/usr/local/lib/python3.6", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 205 entries */, 32768) = 6824
getdents(3, /* 0 entries */, 32768) = 0
中的相同代码musl
:
open("/usr/local/lib/python3.6", O_RDONLY|O_DIRECTORY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
getdents64(3, /* 62 entries */, 2048) = 2040
getdents64(3, /* 61 entries */, 2048) = 2024
getdents64(3, /* 60 entries */, 2048) = 2032
getdents64(3, /* 22 entries */, 2048) = 728
getdents64(3, /* 0 entries */, 2048) = 0
我并不是说这是关键的区别,但是减少核心库中的I / O操作数量可能有助于提高性能。从差异中可以看到,执行完全相同的Python代码可能会导致稍微不同的系统调用。最重要的可能是优化循环性能。我没有足够的资格来判断性能问题是由内存分配还是其他指令引起的。
glibc
10次迭代:
write(1, "0.032388824969530106\n", 210.032388824969530106)
musl
10次迭代:
write(1, "0.035214247182011604\n", 210.035214247182011604)
musl
慢0.0028254222124814987秒。随着差异随着迭代次数的增加而增加,我认为差异在于JSON对象的内存分配。
如果将基准降低为仅导入基准,json
我们会注意到差异并不大:
$ BENCHMARK="import timeit; print(timeit.timeit('import json;', number=5000))"
$ docker run python:3-slim python -c "$BENCHMARK"
0.03683806210756302
$ docker run python:3-alpine3.6 python -c "$BENCHMARK"
0.038280246779322624
加载Python库看起来相当。发电list()
产生较大的差异:
$ BENCHMARK="import timeit; print(timeit.timeit('list(range(10000))', number=5000))"
$ docker run python:3-slim python -c "$BENCHMARK"
0.5666235145181417
$ docker run python:3-alpine3.6 python -c "$BENCHMARK"
0.6885563563555479
显然,最昂贵的操作是json.dumps()
,这可能表明这些库之间的内存分配存在差异。
再次查看基准测试,
musl
实际上在内存分配方面会稍微慢一些:
musl | glibc
-----------------------+--------+--------+
Tiny allocation & free | 0.005 | 0.002 |
-----------------------+--------+--------+
Big allocation & free | 0.027 | 0.016 |
-----------------------+--------+--------+
我不确定“大分配”的含义是什么,但是musl
慢了将近2倍,当您重复执行数千或数百万次此类操作时,这可能会变得很重要。