2012-03-12 30 views
12

Tôi đang sử dụng chức năng I/O mức thấp 'viết' để ghi một số dữ liệu vào đĩa trong mã của tôi (ngôn ngữ C trên Linux). Đầu tiên, tôi tích lũy dữ liệu trong bộ nhớ đệm, và sau đó tôi sử dụng 'write' để ghi dữ liệu vào đĩa khi bộ đệm đầy. Vậy kích thước bộ đệm tốt nhất cho 'viết' là gì? Theo các bài kiểm tra của tôi, nó không phải là lớn hơn nhanh hơn, vì vậy tôi ở đây để tìm câu trả lời.kích thước bộ đệm thích hợp cho chức năng 'ghi' là gì?

+0

+1 để đặt câu hỏi hay ... Tôi luôn muốn biết kích thước phù hợp cho chức năng viết .... – aProgrammer

+0

có thể trùng lặp với [Kích thước bộ đệm tối ưu cho ghi (2)] (http://stackoverflow.com/câu hỏi/8803515/tối ưu-bộ đệm-kích thước-cho-ghi2) – Raedwald

Trả lời

3

Có thể có một số lợi thế khi thực hiện việc ghi là bội số của kích thước khối hệ thống tệp, đặc biệt nếu bạn đang cập nhật tệp tại chỗ. Nếu bạn viết ít hơn một phần khối cho một tập tin, hệ điều hành phải đọc khối cũ, kết hợp trong các nội dung mới và sau đó viết nó ra. Điều này không nhất thiết xảy ra nếu bạn nhanh chóng viết các phần nhỏ theo thứ tự vì các bản cập nhật sẽ được thực hiện trên bộ đệm trong bộ nhớ bị xóa sau này. Tuy nhiên, thỉnh thoảng bạn có thể kích hoạt một số không hiệu quả nếu bạn không điền vào một khối (và một khối được căn chỉnh chính xác: nhiều kích thước khối ở độ lệch là bội số của kích thước khối) với mỗi thao tác ghi.

Vấn đề về kích thước truyền này không nhất thiết phải biến mất với mmap. Nếu bạn ánh xạ một tệp, và sau đó memcpy một số dữ liệu vào bản đồ, bạn đang làm một trang bị bẩn. Trang đó phải được xóa sạch vào một thời gian sau đó: nó không xác định khi nào. Nếu bạn thực hiện một trang khác memcpy chạm vào cùng một trang, trang đó có thể sạch sẽ ngay bây giờ và bạn đang làm cho nó trở nên bẩn. Vì vậy, nó được viết hai lần. Bản sao được sắp xếp theo tỷ lệ bội số của một kích thước trang sẽ là cách để đi.

3

Bạn sẽ muốn nó là bội số của kích thước trang CPU, để sử dụng bộ nhớ hiệu quả nhất có thể.

Nhưng lý tưởng là bạn muốn sử dụng mmap thay vào đó, để bạn không bao giờ phải tự xử lý bộ đệm.

+0

+1 để sử dụng mmap –

+0

Vì vậy, nếu bạn muốn ghi ra 3GB dữ liệu, bạn có thể tạo một bản 3 GB mmap không? Haha. Bạn có thể tạo một tệp mmap nhỏ hơn và sau đó remap nó khi bạn duyệt qua tệp, điều này phức tạp hơn. Đối với không có bộ đệm: tốt, mmap là gì? Đó là một khu vực của bộ nhớ với một con trỏ cơ bản, và một số con trỏ hiện tại cho bạn biết nơi để memcpy phần tiếp theo. Và kích thước lý tưởng cho những hoạt động memcpy đó là gì? Nếu bạn sao chép 300 byte ở đây, 300 byte ở đó, bạn có thể kích hoạt các lệnh xóa tối ưu phụ. I E. CPU có thể bắt bạn làm cho cùng một trang bẩn hai lần và tuôn ra nó hai lần. – Kaz

+0

nếu dữ liệu được xử lý lớn hơn nhiều so với RAM thì sao? –

1

Tùy thuộc vào số lượng RAM, VM, v.v. cũng như lượng dữ liệu được ghi. Câu trả lời chung hơn là chuẩn cho bộ đệm nào hoạt động tốt nhất cho tải bạn đang xử lý và sử dụng những gì hoạt động tốt nhất.

+1

cách tốt nhất để tính số tiền thích hợp cho tất cả Điều này – pyCthon

+0

Lặp lại thông qua các thiết lập khác nhau cho kích thước bộ đệm và điểm chuẩn không? –

+0

hoạt động tôi đoán tôi đã tự hỏi nếu có một số loại công thức dựa trên ram, vm exc – pyCthon

3

Bạn có thể sử dụng quy định tại BUFSIZ<stdio.h>

Nếu không, sử dụng một bội số nhỏ kích thước trang sysconf(_SC_PAGESIZE) (ví dụ hai lần giá trị đó). Hầu hết các hệ thống Linux đều có các trang 4Kbytes (thường là giống hoặc nhiều trang của kích thước khối hệ thống tệp).

Như câu trả lời khác, sử dụng cuộc gọi hệ thống mmap(2) có thể hữu ích. Các hệ thống GNU (ví dụ: Linux) có phần mở rộng: chuỗi chế độ thứ hai là fopen có thể chứa sau m và khi điều đó xảy ra, GNU libc cố gắng mmap.

Nếu bạn xử lý dữ liệu gần bằng RAM (hoặc một nửa), bạn có thể cũng muốn sử dụng madvise(2) để tinh chỉnh hiệu suất của mmap.

Xem thêm this answer cho một câu hỏi khá giống với câu hỏi của bạn. (Bạn có thể sử dụng 64Kbytes như một kích thước bộ đệm hợp lý).

2

Kích thước "tốt nhất" phụ thuộc rất nhiều vào hệ thống tệp cơ bản.

Các statfstat cuộc gọi điền vào một cấu trúc dữ liệu, struct stat, bao gồm các lĩnh vực sau:

blksize_t st_blksize; /* blocksize for file system I/O */ 

Hệ điều hành có trách nhiệm điền lĩnh vực này với một "kích thước tốt" cho write() khối.Tuy nhiên, điều quan trọng là phải gọi write() với bộ nhớ "được căn chỉnh" (ví dụ: kết quả của các cuộc gọi malloc). Cách dễ nhất để thực hiện điều này là sử dụng giao diện luồng <stdio.h> được cung cấp (với các đối tượng FILE *).

Sử dụng mmap, như trong các câu trả lời khác ở đây, cũng có thể rất nhanh trong nhiều trường hợp. Lưu ý rằng nó không phù hợp với một số loại suối (ví dụ: ổ cắm và ống dẫn).

+0

bạn có nghĩa là fwrite nói chung là nhanh hơn so với viết với một kích thước bộ đệm thích hợp? –

+0

Không nhất thiết phải "nhanh hơn", nhưng nó sẽ nhanh chóng chặn các bản sao trong không gian người dùng khi cần thiết. Hơn nữa, nếu bạn cần viết một chuỗi các chuỗi ngắn khác nhau từ các vị trí khác nhau, nó sẽ thu thập tất cả chúng lại với nhau và truyền một khối có kích thước phù hợp cho hạt nhân, trong một cuộc gọi hệ thống. (Bạn có thể đạt được hiệu ứng tương tự với 'writev' trong một số trường hợp nhưng nó thường hoạt động nhiều hơn giá trị của nó - và thậm chí sau đó hạt nhân có xu hướng phải làm cùng một bản sao bộ nhớ.) – torek

+0

Giá trị này được dự định chính xác, nhưng nó đã bật ra rằng nếu tôi sử dụng giá trị này, nó vẫn còn chậm hơn nếu ví dụ sao chép dữ liệu từ A sang B, bởi vì tôi phải tạo nhiều syscalls theo cách này. – glglgl

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