2012-07-09 17 views
7

Tôi có một nghi ngờ khá cơ bản. Thông thường, tôi phải viết các ứng dụng sử dụng tệp đệm I/O và mỗi khi tôi phải đối mặt với tình trạng khó xử của việc chọn kích thước bộ đệm và tôi sẽ làm thử và lỗi thường xuyên với kết quả khá khó chịu. Tôi muốn biết nếu có bất kỳ phương pháp hoặc thuật toán có thể tự động xác định kích thước bộ đệm tối ưu cho công việc dựa trên nền tảng cơ bản như Teracopy hiện khi xử lý các tập tin trong Windows. Tôi chủ yếu sử dụng Qt cho GUI.Tự động chọn kích thước bộ đệm cho Tệp I/O

Nếu có thể một ví dụ nhỏ trong C/C++/C#/Java được đánh giá rất nhiều!

Cảm ơn!

Trả lời

15

Trong Java, tối ưu thường là khoảng kích thước bộ nhớ cache L1 thường là 32 KB. Trong Java, ít nhất việc chọn 1024 byte hoặc 1 MB không tạo ra nhiều khác biệt (< 20%)

Nếu bạn đọc dữ liệu tuần tự, thường hệ điều hành của bạn đủ thông minh để phát hiện và tìm nạp dữ liệu cho bạn.

Điều bạn có thể làm là như sau. Thử nghiệm này xuất hiện để cho thấy sự khác biệt đáng kể trong các kích thước khối được sử dụng.

public static void main(String... args) throws IOException { 
    for (int i = 512; i <= 2 * 1024 * 1024; i *= 2) 
     readWrite(i); 
} 

private static void readWrite(int blockSize) throws IOException { 
    ByteBuffer bb = ByteBuffer.allocateDirect(blockSize); 
    long start = System.nanoTime(); 
    FileChannel out = new FileOutputStream("deleteme.dat").getChannel(); 
    for (int i = 0; i < (1024 << 20); i += blockSize) { 
     bb.clear(); 
     while (bb.remaining() > 0) 
      if (out.write(bb) < 1) throw new AssertionError(); 
    } 
    out.close(); 
    long mid = System.nanoTime(); 
    FileChannel in = new FileInputStream("deleteme.dat").getChannel(); 
    for (int i = 0; i < (1024 << 20); i += blockSize) { 
     bb.clear(); 
     while (bb.remaining() > 0) 
      if (in.read(bb) < 1) throw new AssertionError(); 
    } 
    in.close(); 
    long end = System.nanoTime(); 
    System.out.printf("With %.1f KB block size write speed %.1f MB/s, read speed %.1f MB/s%n", 
      blockSize/1024.0, 1024 * 1e9/(mid - start), 1024 * 1e9/(end - mid)); 
} 

in

With 0.5 KB block size write speed 96.6 MB/s, read speed 169.7 MB/s 
With 1.0 KB block size write speed 154.2 MB/s, read speed 312.2 MB/s 
With 2.0 KB block size write speed 201.5 MB/s, read speed 438.7 MB/s 
With 4.0 KB block size write speed 288.0 MB/s, read speed 733.9 MB/s 
With 8.0 KB block size write speed 318.4 MB/s, read speed 711.8 MB/s 
With 16.0 KB block size write speed 540.6 MB/s, read speed 1263.7 MB/s 
With 32.0 KB block size write speed 726.0 MB/s, read speed 1370.9 MB/s 
With 64.0 KB block size write speed 801.8 MB/s, read speed 1536.5 MB/s 
With 128.0 KB block size write speed 857.5 MB/s, read speed 1539.6 MB/s 
With 256.0 KB block size write speed 794.0 MB/s, read speed 1781.0 MB/s 
With 512.0 KB block size write speed 676.2 MB/s, read speed 1221.4 MB/s 
With 1024.0 KB block size write speed 886.3 MB/s, read speed 1501.5 MB/s 
With 2048.0 KB block size write speed 784.7 MB/s, read speed 1544.9 MB/s 

gì thử nghiệm này không hiển thị là các ổ cứng chỉ hỗ trợ 60 MB/s đọc và 40 MB/s viết. Tất cả những gì bạn đang thử nghiệm là tốc độ vào và ra khỏi bộ đệm. Nếu đây là ưu tiên duy nhất của bạn, bạn sẽ sử dụng một tệp ánh xạ bộ nhớ.

int blockSize = 32 * 1024; 
ByteBuffer bb = ByteBuffer.allocateDirect(blockSize); 
FileChannel out = new FileOutputStream("deleteme.dat").getChannel(); 
for (int i = 0; i < (1024 << 20); i += blockSize) { 
    bb.clear(); 
    while (bb.remaining() > 0) 
     if (out.write(bb) < 1) throw new AssertionError(); 
} 
out.close(); 

long start = System.nanoTime(); 
FileChannel in = new FileInputStream("deleteme.dat").getChannel(); 
MappedByteBuffer map = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size()); 
in.close(); 
long end = System.nanoTime(); 
System.out.printf("Mapped file at a rate of %.1f MB/s%n", 
     1024 * 1e9/(end - start)); 

in

Mapped file at a rate of 589885.5 MB/s 

Đây là quá nhanh bởi vì nó chỉ ánh xạ dữ liệu trong bộ nhớ cache đĩa hệ điều hành trực tiếp vào bộ nhớ của ứng dụng (vì vậy không sao chép được yêu cầu)

+0

Awesomeness tinh khiết !!! Đây gần như là thần như trong Java ... nhưng tôi không biết làm thế nào đến nay tôi có thể thực hiện điều này trên C/C++ như hầu hết các ứng dụng của tôi là bản địa và cần phải càng nhanh càng tốt. Một điều nữa: Phương pháp của bạn có tốt cho các ứng dụng hoạt động trên dữ liệu trước khi ghi lại (ứng dụng mã hóa) không ?? BTW, Math.pow ("Thanks !!!!", (10/0)); –

+0

ứng dụng mã hóa, giống như hầu hết các ứng dụng xử lý, dữ liệu có khả năng bị ràng buộc CPU. Trong trường hợp này, kích thước bộ đệm là không quan trọng vì chi phí CPU quá cao. Kích thước của bộ nhớ cache của bạn có thể tạo ra nhiều sự khác biệt. IMHO Mọi thứ bạn có thể làm trong Java bạn có thể làm trong C hoặc C++. –

+1

Xem giải thích tốt, tôi +1 – aswzen

1

Tôi có xem mã này trong C:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
    struct stat fi; 
    stat("/", &fi); 
    printf("%d\n", fi.st_blksize); 
    return 0; 
} 

Nó trả lại kích thước khối tối ưu. Bạn cần sử dụng nó để làm điều đó. Tôi sử dụng nguồn luồng đến đích với kích thước khối 16 * để có hiệu suất tối ưu. Bởi vì thử nghiệm này sẽ tiết lộ tốt nhất với một máy tính lúc nhàn rỗi với một số phần cứng/hệ điều hành. Nhưng không phải trường hợp thực sự.

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