TL; DR - VẤN ĐỀ 21118
Câu chuyện dài
Josh Rosenberg phát hiện ra rằng str.translate()
chức năng này rất chậm so với bytes.translate
, ông đã nêu ra một vấn đề , nói rằng:
Trong Python 3, str.translate()
thường là sự bi quan về hiệu năng, không phải tối ưu hóa.
Tại sao str.translate()
chậm?
Lý do chính cho str.translate()
việc rất chậm là việc tra cứu được sử dụng trong từ điển Python.
Việc sử dụng maketrans
làm cho vấn đề này tồi tệ hơn. Cách tiếp cận tương tự bằng cách sử dụng bytes
xây dựng một mảng C gồm 256 mục để tra cứu bảng nhanh. Do đó việc sử dụng Python cấp cao hơn dict
làm cho str.translate()
Python 3,4 rất chậm.
Chuyện gì đã xảy ra bây giờ?
Cách tiếp cận đầu tiên là thêm một bản vá nhỏ, translate_writer , Tuy nhiên, việc tăng tốc độ không phải là điều dễ chịu. Ngay sau đó, một bản vá khác fast_translate đã được thử nghiệm và nó mang lại kết quả rất tốt khi tăng tốc lên tới 55%.
Thay đổi chính có thể thấy từ tệp là tra cứu từ điển Python được thay đổi thành tra cứu cấp độ C.
Tốc độ bây giờ gần giống như bytes
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
Một lưu ý nhỏ ở đây là việc tăng cường hiệu năng chỉ nổi bật trong các chuỗi ASCII.
Như JFSebastian đề cập trong một bình luận bên dưới, Trước 3.5, dịch được sử dụng để hoạt động theo cùng một cách cho cả trường hợp ASCII và không phải ASCII. Tuy nhiên từ trường hợp 3.5 ASCII nhanh hơn nhiều.
Trước đây ASCII so với non-ascii trước đây gần như giống nhau, tuy nhiên bây giờ chúng ta có thể thấy một sự thay đổi lớn trong hiệu suất.
Nó có thể là một sự cải tiến từ 71,6μ đến 2,33 as như đã thấy trong câu trả lời này .
Các mã sau đây chứng minh điều này
python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop
python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop
Lập bảng kết quả:
Python 3.4 Python 3.5
Ascii 91.2 2.3
Unicode 101 117
dict.fromkeys(ord(c) for c in '@#$')
?