Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

วิธีเพิ่มประสิทธิภาพการอ่านไฟล์ใน Python ด้วยฟังก์ชัน MMAP

บทนำ

MMAP (Memory Mapping) เมื่อแมปกับไฟล์ จะใช้หน่วยความจำเสมือน (virtual memory) ของระบบปฏิบัติการ เพื่อเข้าถึงข้อมูลบนระบบไฟล์โดยตรง แทนที่จะใช้ I/O functions ปกติ ทำให้ประสิทธิภาพ I/O ดีกว่า เพราะไม่ต้อง system call ทุกครั้ง หรือ copy ข้อมูลระหว่าง buffers

ไฟล์ที่ memory-mapped สามารถจัดการได้เหมือน mutable strings หรือ file-like objects ขึ้นอยู่กับการใช้งาน MMAP รองรับเมธอดมากมาย: close(), flush(), read(), readline(), seek(), tell(), write() และทำงานกับ slice operations และ regular expressions ได้ดี

ขั้นตอนการทำงาน

1. เตรียมไฟล์ข้อความตัวอย่าง

สร้างไฟล์ input.txt ด้วยข้อความ Lorem Ipsum ยาวๆ

2. ใช้ mmap() สร้าง memory-mapped file

ส่ง filename ผ่าน fileno() ของ file object หรือ os.open() พารามิเตอร์ที่สองคือขนาด (bytes) ที่จะแมป ถ้าเป็น 0 จะแมปทั้งไฟล์ มีอาร์กิวเมนต์เพิ่มเติม: ACCESS_READ (อ่านอย่างเดียว), ACCESS_WRITE (เขียนทับ), ACCESS_COPY (copy-on-write)


import mmap

input_text = """Lorem ipsum dolor sit amet, causae apeirian ea his..."""
input_file = 'input.txt'

# create input file
f = open(input_file, "w+")
f.write(input_text)
f.close()

# Open file read-only, map entire file (0)
with open(input_file, 'r') as f:
    with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:
        print(f"Output \n*** Output first 5 bytes of the {input_file} is {m.read(5)}")
        print(f"*** Output Next 10 bytes of the {input_file} is {m.read(10)}")

ผลลัพธ์:


*** Output first 5 bytes of the input.txt is b'Lorem'
*** Output Next 10 bytes of the input.txt is b' ipsum dol'

3. อ่านต่อเนื่อง

หลัง read(5) file pointer จะอยู่ที่ byte ที่ 6 การ read(10) ครั้งต่อไปจะอ่าน byte ที่ 6-15

4. แก้ไขไฟล์แบบ In-place

เปิดไฟล์ mode 'r+' (ไม่ใช่ 'w') ก่อนแมป


import mmap
import shutil

input_file = 'input.txt'
input_copy = input_file.replace('input', 'input_copy')
shutil.copyfile(input_file, input_copy)  # backup

word = b'ipsum'
modified_word = word[::-1]  # reverse: 'muspi'

with open(input_copy, 'r+') as f:
    with mmap.mmap(f.fileno(), 0) as m:
        print(f"output \n *** Line before updates \n {m.readline().rstrip()}")
        m.seek(0)  # rewind
        loc = m.find(word)
        m[loc:loc + len(word)] = modified_word
        m.flush()
        m.seek(0)
        print(f" \n *** Line after updates \n {m.readline().rstrip()}")
    f.seek(0)
    print(f" \n *** Final file \n {f.readline().rstrip()}")

ผลลัพธ์: คำว่า "ipsum" ถูกแทนที่ด้วย "muspi" ทั้งในหน่วยความจำและไฟล์จริง

5. แก้ไขเฉพาะในหน่วยความจำ (ไม่เขียนลงดิสก์)

ใช้ ACCESS_COPY


with open(input_copy, 'r+') as f:
    with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_COPY) as m:
        # ... same logic ...
        # การเปลี่ยนแปลงจะอยู่ใน memory เท่านั้น ไฟล์จริงไม่เปลี่ยน

สังเกตว่า ไฟล์จริงไม่เปลี่ยนแปลง ขณะที่ใน memory เปลี่ยนแล้ว

สรุป

MMAP ช่วยเพิ่มประสิทธิภาพ I/O อย่างมากเหมาะสำหรับไฟล์ขนาดใหญ่ ที่ต้องการ random access หรือแก้ไขบางส่วนโดยไม่ต้องโหลดทั้งไฟล์เข้าหน่วยความจำ