Tôi đã chạy điểm chuẩn giống như bạn đã làm, chỉ sử dụng 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
dẫn đến chênh lệch hơn 2 giây:
$ docker run python:3-slim python -c "$BENCHMARK"
3.6475560404360294
$ docker run python:3-alpine3.6 python -c "$BENCHMARK"
5.834922112524509
Alpine đang sử dụng một triển khai khác libc
(thư viện hệ thống cơ sở) từ dự án musl ( URL phản chiếu ). Có nhiều sự khác biệt giữa các thư viện . Do đó, mỗi thư viện có thể hoạt động tốt hơn trong một số trường hợp sử dụng nhất định.
Đây là một khác biệt giữa các lệnh trên . Đầu ra bắt đầu khác với dòng 269. Tất nhiên có các địa chỉ khác nhau trong bộ nhớ, nhưng nếu không thì nó rất giống nhau. Hầu hết thời gian rõ ràng là dành cho việc chờ python
lệnh kết thúc.
Sau khi cài đặt strace
vào cả hai container, chúng ta có thể có được một dấu vết thú vị hơn (Tôi đã giảm số lần lặp trong điểm chuẩn xuống còn 10).
Ví dụ: glibc
đang tải các thư viện theo cách sau (dòng 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
Cùng một mã trong 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
Tôi không nói rằng đây là điểm khác biệt chính, nhưng việc giảm số lượng thao tác I / O trong các thư viện lõi có thể góp phần mang lại hiệu suất tốt hơn. Từ diff bạn có thể thấy rằng việc thực thi cùng một mã Python có thể dẫn đến các cuộc gọi hệ thống hơi khác nhau. Có lẽ điều quan trọng nhất có thể được thực hiện trong việc tối ưu hóa hiệu suất vòng lặp. Tôi không đủ trình độ để đánh giá xem vấn đề hiệu năng có phải do cấp phát bộ nhớ hoặc một số hướng dẫn khác không.
glibc
với 10 lần lặp:
write(1, "0.032388824969530106\n", 210.032388824969530106)
musl
với 10 lần lặp:
write(1, "0.035214247182011604\n", 210.035214247182011604)
musl
chậm hơn 0,0028254222124814987 giây. Khi sự khác biệt tăng theo số lần lặp, tôi giả sử sự khác biệt nằm ở việc cấp phát bộ nhớ cho các đối tượng JSON.
Nếu chúng tôi giảm điểm chuẩn xuống chỉ nhập, json
chúng tôi nhận thấy sự khác biệt không quá lớn:
$ 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
Đang tải thư viện Python có vẻ tương đương. Tạo list()
ra sự khác biệt lớn hơn:
$ 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
Rõ ràng hoạt động đắt nhất là json.dumps()
, có thể chỉ ra sự khác biệt trong phân bổ bộ nhớ giữa các thư viện đó.
Nhìn lại điểm chuẩn ,
musl
việc phân bổ bộ nhớ thực sự chậm hơn một chút:
musl | glibc
-----------------------+--------+--------+
Tiny allocation & free | 0.005 | 0.002 |
-----------------------+--------+--------+
Big allocation & free | 0.027 | 0.016 |
-----------------------+--------+--------+
Tôi không chắc ý nghĩa của "phân bổ lớn" là gì, nhưng musl
chậm hơn gần 2 lần, điều này có thể trở nên quan trọng khi bạn lặp lại các hoạt động như vậy hàng ngàn hoặc hàng triệu lần.