TL; DR - ปัญหา 21118
เรื่องยาว
Josh Rosenberg พบว่าstr.translate()
ฟังก์ชั่นนี้ช้ามากเมื่อเทียบกับbytes.translate
เขายกปัญหาโดยระบุว่า:
ใน Python 3 str.translate()
มักจะเป็นการมองในแง่ร้ายของประสิทธิภาพไม่ใช่การเพิ่มประสิทธิภาพ
ทำไมถึงstr.translate()
ช้า?
สาเหตุหลักที่ทำให้str.translate()
ช้ามากคือการค้นหาเคยอยู่ในพจนานุกรม Python
การใช้งานmaketrans
ทำให้ปัญหานี้แย่ลง วิธีการที่คล้ายกันโดยใช้bytes
สร้างอาร์เรย์ C จำนวน 256 รายการเพื่อค้นหาตารางอย่างรวดเร็ว ดังนั้นการใช้ Python ระดับที่สูงขึ้นdict
ทำให้str.translate()
ใน Python 3.4 ช้ามาก
เกิดอะไรขึ้นตอนนี้?
แนวทางแรกคือการเพิ่มโปรแกรมแก้ไขขนาดเล็กtranslate_writerอย่างไรก็ตามการเพิ่มความเร็วนั้นไม่เป็นที่พอใจนัก ในไม่ช้าfast_translateแพทช์อื่นก็ได้รับการทดสอบและให้ผลลัพธ์ที่ดีมากด้วยการเร่งความเร็วสูงสุดถึง 55%
การเปลี่ยนแปลงหลักที่เห็นได้จากไฟล์คือการค้นหาพจนานุกรม Python เปลี่ยนเป็นการค้นหาระดับ C
ความเร็วตอนนี้ใกล้เคียงกับ bytes
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
หมายเหตุเล็กน้อยที่นี่คือการเพิ่มประสิทธิภาพการทำงานมีความโดดเด่นเฉพาะในสตริง ASCII
ดังที่ JFSebastian กล่าวไว้ในความคิดเห็นด้านล่างก่อน 3.5 แปลว่าเคยทำงานในลักษณะเดียวกันสำหรับทั้งกรณี ASCII และไม่ใช่ ASCII อย่างไรก็ตามจาก 3.5 ASCII case นั้นเร็วกว่ามาก
ASCII กับ non-ascii ก่อนหน้านี้เคยเกือบจะเหมือนกันอย่างไรก็ตามตอนนี้เราสามารถเห็นการเปลี่ยนแปลงที่ดีในประสิทธิภาพ
สามารถปรับปรุงจาก71.6μsเป็น2.33μsดังที่เห็นในคำตอบนี้
รหัสต่อไปนี้แสดงให้เห็นถึงสิ่งนี้
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
การจัดตารางผลลัพธ์:
Python 3.4 Python 3.5
Ascii 91.2 2.3
Unicode 101 117
dict.fromkeys(ord(c) for c in '@#$')
ไหม: ?