Cách thông thường để đọc một tập tin trong C++ là một trong những điều này:cách Fancy để đọc một tập tin trong C++: hiệu suất lạ vấn đề
std::ifstream file("file.txt", std::ios::binary | std::ios::ate);
std::vector<char> data(file.tellg());
file.seekg(0, std::ios::beg);
file.read(data.data(), data.size());
Đọc một tập tin 1.6 MB gần như ngay lập tức.
Nhưng gần đây, tôi đã phát hiện std::istream_iterator và muốn dùng thử để viết mã một chiều đẹp để đọc nội dung của tệp. Như thế này:
std::vector<char> data(std::istream_iterator<char>(std::ifstream("file.txt", std::ios::binary)), std::istream_iterator<char>());
Mã đẹp, nhưng rất chậm. Mất khoảng 2/3 giây để đọc cùng một tệp 1.6 MB. Tôi hiểu rằng đó có thể không phải là cách tốt nhất để đọc tệp nhưng tại sao lại là vì vậy chậm?
Đọc một tập tin theo một cách cổ điển đi như thế này (tôi đang nói chỉ về chức năng đọc):
- các istream chứa một filebuf chứa một khối dữ liệu từ tập tin
- sự gọi hàm số sgetn từ filebuf, sao chép từng ký tự một (không có memcpy) từ bộ đệm bên trong sang bộ đệm "dữ liệu"
- khi dữ liệu bên trong của filebuf được đọc hoàn toàn, filebuf đọc khối tiếp theo từ tệp
Khi bạn đọc một tập tin sử dụng istream_iterator, nó đi như thế này:
- vector gọi * iterator để có được những char tiếp theo (điều này chỉ đơn giản là đọc một biến), thêm nó đến cùng và tăng riêng của mình kích thước
- nếu không gian được phân bổ của vector đầy (thường xảy ra không thường xuyên), việc di chuyển được thực hiện
- thì nó sẽ gọi ++ iterator đọc char kế tiếp từ luồng (toán tử >> với tham số char chắc chắn chỉ cần gọi hàm sbumpc của filebuf)
- cuối cùng nó so sánh trình lặp với trình lặp kết thúc, được thực hiện bằng cách so sánh hai con trỏ
Tôi phải thừa nhận rằng cách thứ hai không hiệu quả, nhưng ít nhất là 200 lần so với cách đầu tiên, làm sao có thể ?
Tôi nghĩ rằng kẻ giết người thực hiện là chuyển vị trí hoặc chèn, nhưng tôi đã thử tạo toàn bộ vectơ và gọi std :: copy và nó cũng chậm.
// also very slow:
std::vector<char> data2(1730608);
std::copy(std::istream_iterator<char>(std::ifstream("file.txt", std::ios::binary)), std::istream_iterator<char>(), data2.begin());
"Tôi nghĩ rằng kẻ giết người hiệu suất là việc di chuyển hoặc chèn" - đây là lý do tại sao bạn cần phải dựa vào hồ sơ. –