2011-08-24 36 views
6

Tôi đang xử lý một số tệp văn bản theo từng dòng bằng cách sử dụng BufferReader.readlLine().Hiệu suất thấp với BufferedReader

Hai tệp có cùng kích thước 130MB nhưng một tệp mất 40 giây để được xử lý trong khi các tệp khác mất 75 giây.

Tôi nhận thấy một tệp có 1,8 triệu dòng trong khi các tệp khác có 2,1 triệu. Nhưng khi tôi cố gắng xử lý một tệp có 3,0 triệu dòng có cùng kích thước thì phải mất 30 phút để xử lý.

Vì vậy, câu hỏi của tôi là:

  1. là hành vi này vì thời gian tìm kiếm của người đọc đệm (Tôi muốn biết làm thế nào BufferedReader công trình hoặc phân tích các dòng tập tin bằng dòng?)

  2. Có bất kỳ cách nào tôi có thể đọc các dòng tập tin bằng một cách nhanh hơn?

Ok bạn bè, tôi đang cung cấp thêm một số chi tiết.

Tôi chia dòng thành ba phần bằng cách sử dụng regex, sau đó sử dụng SimpleUnsortedWriter (do Cassandra cung cấp) Tôi viết nó vào một số tệp dưới dạng khóa, cột và giá trị. Sau khi dữ liệu 16MB được xử lý, nó sẽ chuyển sang đĩa.

Nhưng logic xử lý giống nhau đối với tất cả các tệp, thậm chí một tệp có kích thước 330MB nhưng ít hơn không có dòng khoảng 1 triệu được xử lý trong 30 giây. Điều gì có thể là lý do?

deviceWriter = new SSTableSimpleUnsortedWriter(
     directory, 
     keyspace, 
     "Devices", 
     UTF8Type.instance, 
     null, 
     16); 

Pattern pattern = Pattern.compile("[\\[,\\]]"); 
while ((line = br.readLine()) != null)   
{ 
    //split the line i n row column and value 
    long timestamp = System.currentTimeMillis() * 1000; 
    deviceWriter .newRow(bytes(rowKey)); 
    deviceWriter .addColumn(bytes(colmName), bytes(value), timestamp); 

} 

Đã thay đổi -Xmx256M to -Xmx 1024M nhưng không giúp ích gì.

Cập nhật: Theo quan sát của tôi, khi tôi viết vào bộ đệm (trong bộ nhớ vật lý), là không. viết vào bộ đệm đang tăng các ghi mới hơn đang dành thời gian. (Đây là dự đoán của tôi)

Vui lòng trả lời.

+3

Vui lòng đăng mã của bạn sử dụng BufferReader – razlebe

+1

Có thể nó không liên quan đến BufferedReader, nhưng với quá trình xử lý bạn thực hiện với mỗi dòng. – Marcelo

Trả lời

6

Điều duy nhất BufferedReader không được đọc từ cơ bản Reader thành một char[] đệm nội bộ với kích thước mặc định của 8K, và tất cả các phương pháp làm việc trên đệm mà cho đến nó đã cạn kiệt, tại thời điểm đó một 8K khác (hoặc bất kỳ thứ gì) được đọc từ số Reader bên dưới. Các readLine() là loại tacked trên.

Sử dụng chính xác BufferedReader chắc chắn là không phải dẫn đến thời gian chạy tăng từ 40 giây tại 1.8m đường lên 30 phút ở 3 m đường. Phải có điều gì đó sai với mã của bạn. Cho chúng tôi xem. Một khả năng khác là JVM của bạn không có đủ bộ nhớ heap và dành hầu hết 30 phút để thu gom rác vì heap của nó đầy 99% và cuối cùng bạn sẽ nhận được OutOfMemoryError với đầu vào lớn hơn. Bạn đang làm gì với các dòng bạn đã xử lý? Chúng được giữ trong ký ức? Việc chạy chương trình có tùy chọn dòng lệnh -Xmx 1024M có tạo sự khác biệt không?

+0

xin cảm ơn ... đã cung cấp thêm một số chi tiết về vấn đề của tôi, vui lòng xem qua – samarth

+0

@samarth: Tôi không thấy điều gì sai với mã bạn đã đăng . Giải pháp đơn giản nhất có thể là làm một số lược tả đơn giản với VisualVM. Điều đó sẽ cho bạn biết tất cả thời gian được chi tiêu, điều này có thể sẽ dẫn bạn trực tiếp đến nguyên nhân của vấn đề. –

1

BufferedReader sẽ không tìm kiếm, nó chỉ đơn giản lưu trữ các ký tự cho đến khi một dòng mới được tìm thấy và trả về dòng như một String, loại bỏ (tái sử dụng) bộ đệm sau mỗi dòng. Đó là lý do tại sao bạn có thể sử dụng nó với bất kỳ luồng hoặc trình đọc nào khác, ngay cả những luồng không hỗ trợ tìm kiếm.

Vì vậy, số lượng các dòng đơn lẻ không nên tạo sự khác biệt lớn ở cấp độ trình đọc. Tuy nhiên, một dòng rất dài có thể tạo ra một chuỗi rất lớn và phân bổ rất nhiều RAM, nhưng dường như không phải là trường hợp của bạn (trong trường hợp đó có thể sẽ ném một ngoại lệ OutOfMemory vượt quá thời gian GC hoặc tương tự).

Đối với những gì tôi có thể thấy trong mã của bạn, bạn không làm gì sai. Tôi cho rằng bạn đang đánh một số loại giới hạn, vì nó không có vẻ là RAM, có lẽ nó có cái gì đó để làm với một số giới hạn cứng ở phía Cassandra? Bạn đã thử bình luận ra phần viết trên Cassandra chưa? chỉ để xem nếu đó là bên của bạn hoặc bên Cassandra đang gây ra vấn đề.

+0

xin cảm ơn ... đã cung cấp thêm một số chi tiết về vấn đề của tôi, vui lòng xem qua – samarth

+0

Câu trả lời đã chỉnh sửa sau khi xem mã của bạn. –

1

Nhìn vào NIO được đệm khi chúng được tối ưu hóa nhiều hơn BufferReader.

Một số đoạn mã từ một diễn đàn khác.http://www.velocityreviews.com/forums/t719006-bufferedreader-vs-nio-buffer.html

FileChannel fc = new FileInputStream("File.txt").getChannel(); 
ByteBuffer buffer = ByteBuffer.allocate(1024); 
fc.read(buffer); 

Edit: Ngoài ra lookinto chủ đề này Read large files in Java

+0

xin cảm ơn ... đã cung cấp thêm một số chi tiết về vấn đề của tôi, vui lòng xem qua số – samarth

1

BufferedReader có lẽ không phải là gốc của vấn đề hiệu suất của bạn.

Dựa trên những con số bạn trích dẫn, có vẻ như bạn có một số phức tạp bậc hai trong mã của mình. Ví dụ: đối với mỗi dòng bạn đọc, bạn đang kiểm tra lại mọi dòng bạn đã đọc trước đó. Tôi chỉ cần suy đoán ở đây, nhưng một ví dụ phổ biến của vấn đề sẽ được sử dụng một cấu trúc dữ liệu danh sách, và kiểm tra để xem nếu dòng mới phù hợp với bất kỳ dòng trước đó.

+0

xin cảm ơn ... đã cung cấp thêm một số chi tiết về vấn đề của tôi, vui lòng xem qua – samarth

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