ฉันใช้มาตรฐานเดียวกันกับที่คุณเคยใช้เพียง 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
อัลไพน์กำลังใช้การนำไปใช้ที่แตกต่างกันของlibc
(ไลบรารีระบบพื้นฐาน) จากโครงการmusl ( URL URL ) มีหลายที่มีความแตกต่างระหว่างห้องสมุดเหล่านั้น เป็นผลให้แต่ละไลบรารีอาจทำงานได้ดีขึ้นในบางกรณีการใช้งาน
นี่คือความแตกต่างระหว่างคำสั่ง strace ที่สูงกว่า เอาต์พุตเริ่มแตกต่างจากบรรทัด 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
การโหลดไลบรารี่ของหลามดูคล้ายคลึงกัน การสร้าง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 เท่าซึ่งอาจมีความสำคัญเมื่อคุณทำซ้ำการดำเนินการดังกล่าวเป็นพัน ๆ ครั้งหรือหลายล้านครั้ง