Một số phép đo hiệu suất, sử dụng timeit
thay vì cố gắng thực hiện bằng tay time
.
Đầu tiên, Apple 2.7.2 64 bit:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop
Bây giờ, python.org 3.3.0 64-bit:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop
In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop
In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.33 s per loop
Rõ ràng, 3.x range
thực sự là chậm hơn so với 2.x một chút xrange
. Và xrange
chức năng của OP không có gì để làm với nó. (Không có gì đáng ngạc nhiên, vì một cuộc gọi một lần đến __iter__
vị trí không có khả năng hiển thị trong số 10000000 cuộc gọi đến bất kỳ điều gì xảy ra trong vòng lặp, nhưng ai đó đã đưa ra như một khả năng.)
Nhưng nó chỉ chậm hơn 30%. Làm thế nào mà OP có được gấp 2 lần chậm? Chà, nếu tôi lặp lại các bài kiểm tra tương tự với Python 32 bit, tôi nhận được 1,58 so với 3,12. Vì vậy, tôi đoán rằng đây là một trường hợp khác trong đó 3.x đã được tối ưu hóa cho hiệu suất 64 bit theo cách làm tổn thương 32 bit.
Nhưng nó thực sự quan trọng? Hãy xem điều này, với 3.3.0 64 bit một lần nữa:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop
Vì vậy, việc xây dựng list
mất nhiều hơn gấp đôi so với toàn bộ lần lặp.
Và đối với "tiêu thụ nhiều tài nguyên hơn Python 2.6+", từ các thử nghiệm của tôi, có vẻ như 3.x range
có kích thước chính xác như 2.x xrange
, và ngay cả khi nó lớn gấp 10 lần, xây dựng danh sách không cần thiết vẫn còn khoảng 10000000x vấn đề hơn bất cứ điều gì mà phép lặp phạm vi có thể làm.
Và những gì về một for
vòng lặp rõ ràng thay vì vòng lặp C bên trong deque
?
In [87]: def consume(x):
....: for i in x:
....: pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop
Vì vậy, gần như lãng phí thời gian trong for
tuyên bố như trong công việc thực tế của việc lặp lại range
.
Nếu bạn lo lắng về việc tối ưu hóa việc lặp lại của một đối tượng phạm vi, có lẽ bạn đang tìm sai chỗ.
Trong khi đó, bạn cứ hỏi tại sao lại xrange
bị xóa, bất kể mọi người nói với bạn điều tương tự bao nhiêu lần, nhưng tôi sẽ nhắc lại lần nữa: Nó không bị xóa: nó được đổi tên thành range
và 2.x range
là những gì đã bị xóa.
Dưới đây là một số bằng chứng cho thấy range
đối tượng 3.3 là hậu duệ trực tiếp của xrange
đối tượng 2.x (chứ không phải của range
chức năng 2.x ): nguồn tới 3.3range
và 2.7xrange
. Bạn thậm chí có thể thấy lịch sử thay đổi (tôi tin rằng, sự thay đổi đã thay thế phiên bản cuối cùng của chuỗi "xrange" ở bất kỳ đâu trong tệp).
Vì vậy, tại sao nó chậm hơn?
Chà, trước tiên, họ đã thêm rất nhiều tính năng mới. Mặt khác, họ đã thực hiện tất cả các loại thay đổi ở mọi nơi (đặc biệt là trong vòng lặp) có tác dụng phụ nhỏ. Và đã có rất nhiều công việc để tối ưu hóa đáng kể các trường hợp quan trọng khác nhau, ngay cả khi đôi khi nó hơi bi quan những trường hợp ít quan trọng hơn. Thêm tất cả điều này lên, và tôi không ngạc nhiên rằng việc lặp lại range
càng nhanh càng tốt bây giờ chậm hơn một chút. Đó là một trong những trường hợp ít quan trọng mà không ai quan tâm đủ để tập trung vào. Không ai có thể có trường hợp sử dụng thực tế trong đó sự khác biệt hiệu suất này là điểm nóng trong mã của họ.
range
trong Python 3.x làxrange
từ Python 2.x. Trên thực tế, Python 2.xrange
đã bị xóa.