Vì thuật toán tôi muốn triển khai sử dụng chỉ số 1..n
và vì rất dễ bị thay đổi từng chỉ mục, tôi quyết định lấy thông minh và chèn phần tử giả vào đầu mỗi danh sách, vì vậy tôi có thể sử dụng công thức gốc từ bài báo.PyPy: Hình phạt hiệu suất nghiêm trọng khi sử dụng None trong danh sách có số nguyên
Vì lợi ích của khó, hãy xem xét ví dụ đồ chơi này:
def calc(N):
nums=[0]+range(1,N+1)
return sum(nums[1:]) #skip first element
Tuy nhiên, tôi đã lo lắng, mà kết quả của tôi là giả mạo, bởi vì tôi có thể truy cập vào các phần tử 0 thứ một cách tình cờ ở đâu đó và không được nhận thức của nó. Vì vậy, tôi thậm chí còn thông minh hơn và sử dụng None
thay vì 0
là yếu tố đầu tiên - mọi hoạt động số học với nó sẽ cho kết quả trong một lỗi runtime:
def calc_safe(N):
nums=[None]+range(1,N+1) #here we use "None"
return sum(nums[1:])
Đáng ngạc nhiên, sự thay đổi nhỏ này đã dẫn đến một hình phạt hiệu quả rất lớn cho PyPy (thậm chí với phiên bản 5.8 hiện tại) - mã đã chậm hơn khoảng 10 lần! Đây là số lần trên máy của tôi:
pypy-5.8 cpython
calc(10**8) 0.5 sec 5.5 sec
calc_safe(10**8) 7.5 sec 5.5 sec
Là nút phụ: Cpython không quan tâm, cho dù None
có được sử dụng hay không.
Vì vậy, câu hỏi của tôi có hai phần:
- Rõ ràng sử dụng
None
không phải là một ý tưởng tốt, nhưng tại sao? - Có thể nhận được sự an toàn của
None
-ứng dụng và giữ hiệu suất không?
Edit: Như Armin đã giải thích, không phải tất cả danh sách đều bình đẳng, và chúng ta có thể thấy, đó là chiến lược được sử dụng thông qua:
import __pypy__
print __pypy__.strategy(nums)
Trong trường hợp đầu tiên nó là IntegerListStrategy
và trong lần thứ hai ObjectListStrategy
. Điều tương tự cũng xảy ra nếu chúng tôi sử dụng một giá trị số nguyên lớn (như 2**100
) thay vì None
.
Đó là bằng cách nào đó có thể nhìn thấy một cách rõ ràng, cho dù tối ưu hóa hoặc phiên bản không được tối ưu hóa danh sách được sử dụng? – ead
Có, với '' __pypy __. Strategy (lst) ''. –