2012-06-24 31 views
8

Tôi đang đọc tệp 50G chứa hàng triệu hàng được phân tách bằng ký tự dòng mới. Hiện tại tôi đang sử dụng cú pháp sau để đọc tệpJava Cách cải thiện việc đọc tệp 50 Gigabit

String line = null; 
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("FileName"))); 
while ((line = br.readLine()) != null) 
{ 
// Processing each line here 
// All processing is done in memory. No IO required here. 
} 

Vì tệp quá lớn nên mất 2 giờ để xử lý toàn bộ tệp. Tôi có thể cải thiện việc đọc tệp từ đĩa cứng sao cho hoạt động IO (Đọc) mất ít thời gian nhất. Các hạn chế với mã của tôi là tôi phải xử lý từng dòng thứ tự tuần tự.

+0

Việc triển khai 'BufferedReader' của Java là gì? Có lẽ bạn có thể cải thiện ở đó bằng cách đọc các khối (với kích thước tối ưu cho hệ điều hành và hệ thống tệp) trong một luồng khác. –

+8

Bạn có ý nghĩa 50 Gbit hoặc 50 Gbyte không? –

Trả lời

8

Hy vọng duy nhất của bạn là song song việc đọc và xử lý nội dung bên trong. Chiến lược của bạn nên không bao giờ yêu cầu toàn bộ nội dung tệp phải nằm trong bộ nhớ cùng một lúc.

Bắt đầu bằng cách lập cấu hình mã bạn phải xem thời gian đang được sử dụng. Viết lại phần mất nhiều thời gian nhất và tái cấu hình để xem nó có cải thiện hay không. Tiếp tục lặp lại cho đến khi bạn nhận được kết quả chấp nhận được.

Tôi nghĩ về Hadoop và giải pháp phân tán. Các tập dữ liệu lớn hơn của bạn được xử lý thường xuyên ngay bây giờ. Bạn có thể cần phải sáng tạo hơn một chút trong suy nghĩ của mình.

+0

Lưu ý - Tôi đã xem lại câu trả lời của mình. – duffymo

10

mất 2 giờ để xử lý toàn bộ tệp.

50 GB/2 giờ tương đương với khoảng 7 MB/s. Nó không phải là một tỷ lệ xấu cả. Một đĩa cứng (hiện đại) tốt nên có khả năng duy trì tốc độ cao hơn liên tục, vì vậy có thể nút cổ chai của bạn không phải là I/O? Bạn đã sử dụng BufferedReader, giống như tên cho biết, đang lưu vào bộ đệm (trong bộ nhớ) những gì nó đọc. Bạn có thể thử nghiệm tạo ra các độc giả với bộ đệm lớn hơn một chút so với kích thước mặc định (8192 bytes), như vậy:

BufferedReader br = new BufferedReader(
    new InputStreamReader(new FileInputStream("FileName")), 100000); 

Lưu ý rằng với mặc định 8192 byte đệm và 7 MB/s thông các BufferedReader sẽ tái -Cấp bộ đệm của nó gần 1000 lần mỗi giây, vì vậy việc giảm số lượng đó thực sự có thể giúp cắt giảm một số chi phí. Nhưng nếu việc xử lý mà bạn đang làm, thay vì I/O, là nút cổ chai, thì không có thủ thuật I/O nào sẽ giúp bạn nhiều. Bạn có lẽ nên xem xét làm cho nó đa luồng, nhưng cho dù đó là doable, và làm thế nào, phụ thuộc vào những gì "chế biến" có nghĩa là ở đây.

+2

7MB/s là khủng khiếp đối với ổ đĩa I/O tuyến tính bền vững ... –

+1

Có, các mức giá thông thường hiện nay là bậc cao hơn * trong điểm chuẩn *. Tuy nhiên, RPM đĩa, phân mảnh, vv - và đặc biệt là các chương trình khác và hệ điều hành làm công cụ riêng của họ trong nền - có tác dụng to lớn. 10 MB/s duy trì không phải là một số thực tế xấu cho một máy tính xách tay 5 năm tuổi. –

+3

Tôi cho rằng bạn nói đúng. Tôi đoán tôi đã từng nghĩ về các đĩa mà tôi có xu hướng sử dụng tại nơi làm việc, trong đó 100MB/s được duy trì (trong thực tế) là điển hình. –

5

Nếu không có NIO, bạn sẽ không thể phá vỡ rào cản thông lượng. Ví dụ: thử sử dụng new Scanner(File) thay vì trực tiếp tạo trình đọc. Gần đây tôi đã xem xét mã nguồn đó, nó sử dụng các kênh tập tin của NIO.

Nhưng điều đầu tiên tôi đề xuất là chạy vòng trống với BufferedReader không có gì ngoài việc đọc. Lưu ý các thông lượng - và cũng giữ một mắt trên CPU. Nếu vòng lặp tầng CPU, thì chắc chắn có một vấn đề với mã IO.

+0

Máy quét sử dụng bộ đệm heap, không được ánh xạ bộ đệm trực tiếp. Vì vậy, nó không khác nhiều so với FileInputStream.read (vẫn tốt hơn vì nó không yêu cầu malloc/miễn phí trên mỗi lần đọc khi bộ đệm là> 8KB) – bestsss

2
  1. Tắt chương trình chống vi-rút và bất kỳ chương trình nào khác làm tăng thêm sự tranh chấp đĩa trong khi đọc tệp.

  2. Chống phân mảnh đĩa.

  3. Tạo phân vùng đĩa thô và đọc tệp từ đó.

  4. Đọc tệp từ SSD.

  5. Tạo đĩa RAM 50 GB và đọc tệp từ đó.

1

Tôi nghĩ bạn có thể nhận được kết quả tốt nhất bằng cách xem xét lại vấn đề bạn đang cố giải quyết. Rõ ràng là lý do bạn đang tải tệp 50Gig này. Hãy xem xét nếu không có cách nào tốt hơn để phá vỡ dữ liệu được lưu trữ và chỉ sử dụng dữ liệu bạn thực sự cần.

0

Cách bạn đọc tệp là tốt. Có thể có những cách để làm cho nó nhanh hơn, nhưng nó thường đòi hỏi sự hiểu biết nơi nút cổ chai của bạn là. Bởi vì thông lượng IO thực sự là ở cuối thấp hơn, tôi cho rằng tính toán có hiệu quả phụ. Nếu nó không quá dài bạn có thể cho bạn thấy toàn bộ chương trình.

Hoặc, bạn có thể chạy chương trình của mình mà không có nội dung của vòng lặp và xem mất bao lâu để đọc qua tệp :)

Các vấn đề liên quan