Tôi hiểu rằng cả Java và Perl đều cố gắng tìm một kích thước phù hợp với kích thước bộ đệm mặc định khi đọc trong các tệp, nhưng tôi thấy sự lựa chọn của họ ngày càng lỗi thời và đang gặp sự cố khi thay đổi lựa chọn mặc định đến với Perl. Trong trường hợp Perl, tôi tin rằng sử dụng bộ đệm 8K theo mặc định, tương tự như sự lựa chọn của Java, tôi không thể tìm thấy tham chiếu bằng công cụ tìm kiếm trang web perldoc (thực sự là Google) về cách tăng bộ đệm đầu vào tệp mặc định kích thước để nói, 64K.Làm thế nào tôi có thể đặt kích thước bộ đệm đọc tệp trong Perl để tối ưu hóa nó cho các tệp lớn?
Từ liên kết ở trên, để hiển thị như thế nào 8K bộ đệm không mở rộng:
Nếu dòng thường có khoảng 60 ký tự mỗi, sau đó tập tin 10.000 dòng có khoảng 610.000 nhân vật trong đó. Đọc tập tin theo từng dòng với bộ đệm chỉ yêu cầu 75 cuộc gọi hệ thống và 75 lần chờ cho đĩa thay vì 10.001.
Vì vậy, đối với tệp 50.000.000 dòng với 60 ký tự trên mỗi dòng (bao gồm dòng mới ở cuối), với bộ đệm 8K, nó sẽ thực hiện 366211 cuộc gọi hệ thống để đọc tệp 2,8GiB. Như một sang một bên, bạn có thể xác nhận hành vi này bằng cách nhìn vào đĩa i/o đọc delta (trong Windows ít nhất, đầu trong * nix cho thấy điều tương tự bằng cách nào đó tôi cũng chắc chắn) trong danh sách quá trình quản lý tác vụ như chương trình Perl của bạn mất 10 phút để đọc trong một tệp văn bản :)
Ai đó đã đặt câu hỏi về việc tăng kích thước bộ đệm đầu vào Perl trên perlmonks, ai đó trả lời here mà bạn có thể tăng kích thước "$ /" và do đó tăng kích thước bộ đệm , tuy nhiên, từ perldoc:
Đặt $/để tham chiếu đến số nguyên, vô hướng có thể chuyển thành số nguyên sẽ cố đọc bản ghi thay vì dòng, với kích thước bản ghi tối đa là tài liệu tham khảo d số nguyên.
Vì vậy, tôi cho rằng điều này không thực sự làm tăng kích thước bộ đệm mà Perl sử dụng để đọc trước từ đĩa khi sử dụng tiêu biểu:
while(<>) {
#do something with $_ here
...
}
"line-by-line" thành ngữ.
Bây giờ có thể khác "đọc một bản ghi tại một thời điểm và sau đó phân tích thành dòng" phiên bản của mã trên sẽ nhanh hơn nói chung và bỏ qua vấn đề cơ bản với thành ngữ chuẩn và không thể thay đổi kích thước bộ đệm mặc định (nếu điều đó thực sự không thể), vì bạn có thể đặt "kích thước bản ghi" thành bất kỳ thứ gì bạn muốn và sau đó phân tích từng bản ghi thành từng dòng riêng lẻ, và hy vọng rằng Perl làm điều đúng và kết thúc bằng một hệ thống gọi cho mỗi bản ghi, nhưng nó làm tăng thêm độ phức tạp và tất cả những gì tôi thực sự muốn làm là đạt được hiệu suất dễ dàng bằng cách tăng bộ đệm được sử dụng trong ví dụ trên lên kích thước lớn, 64K hoặc thậm chí điều chỉnh kích thước bộ đệm đó thành kích thước tối ưu cho những lần đọc dài sử dụng tập lệnh thử nghiệm trên hệ thống của tôi, mà không cần thêm rắc rối.
Mọi thứ tốt hơn rất nhiều trong Java theo như hỗ trợ thẳng về phía trước để tăng kích thước bộ đệm.
Trong Java, tôi tin rằng kích thước bộ đệm mặc định hiện tại mà java.io.BufferedReader sử dụng cũng là 8192 byte, mặc dù tài liệu tham khảo cập nhật trong tài liệu JDK là tương đối, ví dụ: 1.5 tài liệu chỉ nói:
Kích thước bộ đệm có thể được chỉ định hoặc kích thước mặc định có thể được chấp nhận. Mặc định là đủ lớn cho hầu hết các mục đích.
May mắn với Java bạn không cần phải tin tưởng các nhà phát triển JDK đã thực hiện quyết định đúng đắn cho các ứng dụng của bạn và có thể thiết lập kích thước bộ đệm riêng của bạn (64K trong ví dụ này):
import java.io.BufferedReader;
[...]
reader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"), 65536);
[...]
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
/* do something with the line here */
foo(line);
}
Chỉ có rất nhiều hiệu suất bạn có thể vắt ra khỏi việc phân tích một dòng tại một thời điểm, ngay cả với bộ đệm khổng lồ và phần cứng hiện đại, và tôi chắc chắn có nhiều cách để có được hiệu suất của việc đọc trong một tệp bằng cách đọc nhiều các bản ghi dòng và bẻ khóa mỗi lần vào các thẻ sau đó thực hiện các công cụ với các mã thông báo đó một lần cho mỗi bản ghi, nhưng chúng thêm các trường hợp phức tạp và cạnh (mặc dù nếu có một giải pháp thanh lịch trong Java thuần túy (chỉ sử dụng các tính năng có trong JDK 1.5) sẽ rất hay khi biết). Tăng kích thước bộ đệm trong Perl sẽ giải quyết được 80% vấn đề hiệu suất cho Perl ít nhất, trong khi vẫn giữ mọi thứ thẳng về phía trước.
Câu hỏi của tôi là:
Có cách nào để điều chỉnh kích thước bộ đệm trong Perl cho điển hình "line-by-line" thành ngữ trên, tương tự như thế nào kích thước bộ đệm được tăng lên trong ví dụ Java?
Thật tuyệt khi đăng liên kết đến một số thông tin khác về xử lý Perl 5.10. –
Điều duy nhất khác với các phiên bản trước đó là xử lý được may mắn vào gói IO :: Handle. Đó là sự khác biệt duy nhất. Đặc biệt, chỉ việc mở một tệp không có nghĩa là bạn có thể gọi bất kỳ phương thức nào trên tay cầm. Bạn phải "sử dụng IO :: Xử lý" để các phương thức được xác định. –
Điều đó không mới trong 5,10; filehandles đã được may mắn vào IO :: Xử lý trong một thời gian dài (hoặc, cho tương thích ngược, vào FileHandle nếu đã được nạp). Nhưng như Elliot nói, các phương thức không được định nghĩa trừ khi bạn sử dụng IO :: Handle. – ysth