मैंने वही बेंचमार्क चलाया है जैसा आपने किया था, सिर्फ पायथन 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
अल्पाइन libc
, मसल प्रोजेक्ट ( मिरर यूआरएल ) से (बेस सिस्टम लाइब्रेरी) के एक अलग कार्यान्वयन का उपयोग कर रहा है । उन पुस्तकालयों के बीच कई अंतर हैं । परिणामस्वरूप, प्रत्येक लाइब्रेरी कुछ उपयोग मामलों में बेहतर प्रदर्शन कर सकती है।
यहां ऊपर दिए गए आदेशों के बीच एक स्ट्रेस अलग है । आउटपुट लाइन 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 संचालन की संख्या को कम करने से बेहतर प्रदर्शन में योगदान हो सकता है। इस अंतर से आप देख सकते हैं कि बहुत ही पायथन कोड को क्रियान्वित करने से कुछ अलग सिस्टम कॉल हो सकते हैं। संभवतः लूप के प्रदर्शन को अनुकूलित करने में सबसे महत्वपूर्ण हो सकता है। मैं यह निर्धारित करने के लिए पर्याप्त योग्य नहीं हूं कि प्रदर्शन का मुद्दा मेमोरी आवंटन या किसी अन्य निर्देश के कारण है या नहीं।
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
लोड हो रहा है अजगर पुस्तकालयों तुलनीय लग रहा है। सृजन से 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 × धीमी है, जो हजारों या लाखों बार इस तरह के संचालन को दोहराने पर महत्वपूर्ण हो सकता है।