Có thể tiết kiệm đáng kể bằng cách tránh chuyển toàn bộ tệp đầu vào của bạn vào bộ nhớ dưới dạng list
trong số các dòng.
Cụ thể, những dòng này rất khủng khiếp về việc sử dụng bộ nhớ, trong đó chúng liên quan đến việc sử dụng bộ nhớ cao nhất là bytes
đối tượng kích thước của toàn bộ tệp của bạn, cộng với một list
trong số các dòng có nội dung đầy đủ của tệp:
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
Đối với tệp văn bản ASCII 1 GB với 5 triệu dòng, trên 64 bit Python 3.3+, đó là yêu cầu bộ nhớ cao nhất khoảng 2,3 GB cho just bytes
đối tượng, list
và str
riêng lẻ s trong list
. Một chương trình cần RAM gấp 2,3 lần kích thước của tệp mà nó xử lý sẽ không mở rộng thành tệp lớn.
Để khắc phục, hãy thay đổi mã gốc đó thành:
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
Cho rằng obj['Body']
dường như có thể sử dụng được cho phát trực tuyến chậm
điều này sẽ loại bỏ cả hai bản sao của dữ liệu tệp hoàn chỉnh từ bộ nhớ. Sử dụng TextIOWrapper
nghĩa là obj['Body']
được đọc và giải mã một cách lười biếng theo từng phần (vài KB tại một thời điểm), và các dòng cũng được lặp lại một cách lười biếng; điều này làm giảm nhu cầu bộ nhớ xuống một lượng nhỏ, phần lớn cố định (chi phí bộ nhớ cao nhất sẽ phụ thuộc vào độ dài của dòng dài nhất), bất kể kích thước tệp.
Cập nhật:
Có vẻ như StreamingBody
không triển khai io.BufferedIOBase
ABC. Nó có API được lập thành văn bản của riêng nó
tuy nhiên, điều đó có thể được sử dụng cho một mục đích tương tự. Nếu bạn không thể tạo TextIOWrapper
làm công việc cho bạn (nó hiệu quả và đơn giản hơn nhiều nếu nó có thể hoạt động), một giải pháp thay thế sẽ là:
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
Không giống như sử dụng TextIOWrapper
, nó không được hưởng lợi từ việc giải mã hàng loạt các khối (mỗi dòng được giải mã riêng lẻ), nhưng nếu không, nó vẫn sẽ đạt được những lợi ích tương tự khi giảm mức sử dụng bộ nhớ.