2009-06-21 39 views
8

Tôi đã cố gắng viết một số mã Java rất nhanh mà phải làm rất nhiều I/O. Tôi đang sử dụng một bộ nhớ ánh xạ tập tin mà trả về một ByteBuffer:Các tệp ánh xạ bộ nhớ trong Java

public static ByteBuffer byteBufferForFile(String fname){ 
    FileChannel vectorChannel; 
    ByteBuffer vector; 
    try { 
     vectorChannel = new FileInputStream(fname).getChannel(); 
    } catch (FileNotFoundException e1) { 
     e1.printStackTrace(); 
     return null; 
    } 
    try { 
     vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    return vector; 
} 

Vấn đề mà tôi đang gặp là phương pháp ByteBuffer .array() (mà nên trả về một mảng byte []) không hoạt động cho các tệp chỉ đọc. Tôi muốn viết mã của tôi để nó sẽ làm việc với cả hai bộ nhớ đệm được xây dựng trong bộ nhớ và bộ đệm đọc từ đĩa. Nhưng tôi không muốn bọc tất cả các bộ đệm của tôi một hàm ByteBuffer.wrap() vì tôi lo lắng rằng điều này sẽ làm chậm mọi thứ. Vì vậy, tôi đã viết hai phiên bản của tất cả mọi thứ, một trong đó có một byte [], một trong đó có một ByteBuffer.

Tôi có nên bọc mọi thứ không? Hay tôi nên viết đôi mọi thứ?

+3

điểm chuẩn và đăng kết quả, ngay cả khi chuyên gia có thể chỉ cho bạn theo một hướng mà hướng có thể không hoạt động cho trường hợp của bạn. Điểm chuẩn !!!! – basszero

Trả lời

10

Có ai thực sự kiểm tra xem liệu ByteBuffers được tạo bằng hỗ trợ ánh xạ bộ nhớ có được gọi .array() ngay từ đầu, bất kể readonly/readwrite không?

Từ việc tôi nói đùa, theo như tôi có thể nói, câu trả lời là NO. Khả năng trả lại một mảng byte[] trực tiếp thông qua ByteBuffer.array() được xác định bởi sự hiện diện của ByteBuffer.hb (byte[]), luôn được đặt thành rỗng khi tạo MappedByteBuffer.

Điều gì khiến tôi buồn, bởi vì tôi đã hy vọng làm điều gì đó tương tự như những gì tác giả câu hỏi muốn làm.

+0

Tôi đồng ý. Nó hút. Tôi không thể tin rằng ByteBuffer không thực hiện mảng(). Mặt khác, chúng tôi đã thực hiện một số thử nghiệm hiệu suất và chúng tôi nhận thấy rằng nó đôi khi nhanh hơn để sử dụng .get() với tệp ánh xạ bộ nhớ hơn là sử dụng chương trình-io và đôi khi nhanh hơn khi sử dụng lập trình-io. Nó rất lạ. Nhưng có nhiều phương sai trên lập trình-io hơn trên các tệp ánh xạ bộ nhớ. – vy32

+3

Một 'byte []' phải nằm trên vùng heap. Khối bộ nhớ được ánh xạ bộ nhớ phải nằm ngoài vùng heap. Nó sẽ là tốt đẹp nếu sự khác biệt là minh bạch, nhưng tôi thích sử dụng phương thức getLong/putLong của một ByteBuffer anyway (đây là nhanh hơn nhiều với việc sử dụng thứ tự bản địa) –

1

Sử dụng chức năng ByteBuffer.wrap() không áp đặt gánh nặng cao. Nó phân bổ một đối tượng đơn giản và khởi tạo một vài số nguyên. Viết thuật toán của bạn để chống lại ByteBuffer do đó đặt cược tốt nhất của bạn nếu bạn cần phải làm việc với các tập tin chỉ đọc.

4

Gói byte [] sẽ không làm chậm mọi thứ ... sẽ không có bất kỳ bản sao mảng lớn nào hoặc các tệ nạn hiệu suất nhỏ khác. Từ JavaDocs: java.nio.ByteBuffer .wrap()

Kết thúc một mảng byte vào bộ đệm.

Bộ đệm mới sẽ được hỗ trợ bởi mảng byte đã cho; nghĩa là, sửa đổi đối với bộ đệm sẽ gây ra mảng cần sửa đổi và phó ngược lại. Dung lượng bộ đệm mới và giới hạn sẽ là array.length, vị trí của nó sẽ bằng 0 và dấu của nó là sẽ không được xác định. Mảng sao lưu của nó sẽ là mảng đã cho và mảng của nó là sẽ là 0.

+0

Cảm ơn. Tôi chỉ quan tâm đến việc phải đọc từng byte bằng .get (i) thay vì [i], vì .get (i) liên quan đến một cuộc gọi phương thức trong khi [i] được thực hiện trong bytecode. – vy32

+4

Điều đó có vẻ giống như một mối quan tâm hiệu suất "tinh vi" tốt, và có mùi như tối ưu hóa sớm với tôi. JVM là tốt về các công cụ như thế này. Đánh dấu nó để chứng minh nó cho chính mình theo cách này hay cách khác. –

+0

Thực ra, tôi đang thực hiện pháp y máy tính, xử lý hàng terabyte thông tin. Theo kinh nghiệm của tôi cho đến nay JVM đã không được tối ưu hóa nhiều như tôi mong đợi. – vy32

5

Không phải lúc nào cũng tốt để không làm mới lại bánh xe. Apache đã cung cấp một thư viện đẹp để thực hiện các hoạt động I/O. Hãy xem http://commons.apache.org/io/description.html

Đây là kịch bản mà nó phục vụ. Giả sử bạn có một số dữ liệu mà bạn muốn thích giữ trong bộ nhớ, nhưng bạn không biết trước thời gian số lượng dữ liệu sẽ có. Nếu có quá nhiều, bạn muốn ghi nó vào đĩa thay vì bộ nhớ hogging, nhưng bạn không muốn ghi vào đĩa cho đến khi bạn cần, vì đĩa chậm và là tài nguyên cần theo dõi để dọn dẹp .

Vì vậy, bạn tạo bộ đệm tạm thời và bắt đầu ghi vào đó. Nếu/khi bạn đạt đến ngưỡng cho những gì bạn muốn giữ trong bộ nhớ, bạn sẽ cần phải tạo tệp, ghi những gì trong bộ đệm vào tệp đó và ghi tất cả dữ liệu tiếp theo vào tệp thay vì bộ đệm .

Đó là những gì DeferredOutputStream không phù hợp với bạn. Nó ẩn tất cả các lộn xộn xung quanh tại thời điểm chuyển đổi. Tất cả những gì bạn cần làm là tạo luồng hoãn lại ở vị trí đầu tiên, định cấu hình ngưỡng và sau đó chỉ cần ghi lại nội dung trái tim của bạn.

CHỈNH SỬA: Tôi vừa thực hiện tìm kiếm lại nhỏ bằng cách sử dụng google và tìm thấy liên kết này: http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (Đọc/ghi tệp nhanh). Rất ấn tượng.

+0

Đúng nếu tôi sai. Bạn đang tìm cách nhanh chóng để thực hiện các hoạt động I/O. Chính xác?? –

+0

Trên thực tế, tôi chỉ đang tìm cách làm nhanh, nhưng tôi cũng đang tìm cách xử lý các vùng đệm với số lượng bản sao đệm tối thiểu. – vy32

+0

@GauravSaini: Bạn có tham khảo 'DeferredOutputStream' từ Apache commons-io không? Tôi không thể tìm thấy lớp như vậy trong Javadoc cho v2.3 & v2.2. –

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