Sadece Python 3 kullanarak aynı kriteri kullandım:
$ docker run python:3-alpine3.6 python --version
Python 3.6.2
$ docker run python:3-slim python --version
Python 3.6.2
2 saniyeden fazla farkla sonuçlanır:
$ docker run python:3-slim python -c "$BENCHMARK"
3.6475560404360294
$ docker run python:3-alpine3.6 python -c "$BENCHMARK"
5.834922112524509
Alpine, musl projesinden farklı bir uygulama libc
(temel sistem kütüphanesi) kullanıyor ( ayna URL'si ). Bu kütüphaneler arasında birçok farklılık var . Sonuç olarak, her kütüphane belirli kullanım durumlarında daha iyi performans gösterebilir.
İşte yukarıdaki komutlar arasında saplı bir fark var . Çıktı, satır 269'dan farklı olmaya başlar. Tabii ki, bellekte farklı adresler vardır, ancak aksi halde çok benzer. Çoğu zaman python
komutun bitmesini beklemekle harcanır .
Her strace
iki kaba da kurduktan sonra daha ilginç bir iz elde edebiliriz (Ben kıyaslamadaki yineleme sayısını 10'a düşürdüm).
Örneğin, glibc
kütüphaneleri aşağıdaki şekilde yüklüyor (satır 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
Aynı kod 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
Bunun önemli bir fark olduğunu söylemiyorum, ancak çekirdek kütüphanelerdeki G / Ç işlemlerinin sayısının azaltılması daha iyi performansa katkıda bulunabilir. Farklılıktan, aynı Python kodunun çalıştırılmasının biraz farklı sistem çağrılarına neden olabileceğini görebilirsiniz. Muhtemelen en önemlisi döngü performansını optimize etmede yapılabilir. Performans sorununun bellek ayırma veya başka bir talimattan kaynaklanıp kaynaklanmadığını yargılayacak kadar nitelikli değilim.
glibc
10 yineleme ile:
write(1, "0.032388824969530106\n", 210.032388824969530106)
musl
10 yineleme ile:
write(1, "0.035214247182011604\n", 210.035214247182011604)
musl
daha yavaş 0,0028254222124814987 saniye daha yavaş. Fark, yinelemelerin sayısıyla birlikte büyüdükçe, farkın JSON nesnelerinin hafıza tahsisinde olduğunu varsayarım.
Göstergeyi yalnızca ithal etmeye json
indirirsek, farkın çok büyük olmadığını fark ediyoruz:
$ 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 kütüphanelerinin yüklenmesi karşılaştırılabilir görünüyor. Üretmek list()
daha büyük farklar üretir:
$ 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
Açıkçası, en pahalı işlem, json.dumps()
bu kütüphaneler arasında bellek paylaşımındaki farklılıklara işaret edebilir.
Tekrar bakıldığında kriter ,
musl
bellek ayrılmasına biraz daha yavaş gerçekten:
musl | glibc
-----------------------+--------+--------+
Tiny allocation & free | 0.005 | 0.002 |
-----------------------+--------+--------+
Big allocation & free | 0.027 | 0.016 |
-----------------------+--------+--------+
"Büyük tahsisat" ile neyin kastedildiğinden emin değilim, ancak musl
neredeyse 2 kat daha yavaş, bu tür işlemleri binlerce veya milyon kez tekrarladığınızda önemli olabilir.