2013-09-03 35 views
7

Tôi có vấn đề sau đây:Zero, một ánh xạ bộ nhớ lớn với `madvise`

tôi bố trí một mảng lớn của bộ nhớ (nhiều GiB) thông qua mmap với MAP_ANONYMOUS. Chunk đó giữ một bản đồ băm lớn mà cần phải được zeroed mỗi bây giờ và sau đó. Không phải toàn bộ ánh xạ có thể được sử dụng trong mỗi vòng (không phải mọi trang đều bị lỗi), do đó, memset không phải là một ý tưởng hay - mất quá nhiều thời gian.

Chiến lược tốt nhất để thực hiện điều này nhanh chóng là gì?

Will

madvise(ptr, length, MADV_DONTNEED); 

bảo đảm với tôi rằng bất kỳ truy cập tiếp theo cung cấp các trang trống mới?

Từ trang Linux man madvise:

Cuộc gọi này không ảnh hưởng đến ngữ nghĩa của các ứng dụng (ngoại trừ trong trường hợp MADV_DONTNEED), nhưng có thể ảnh hưởng đến hiệu quả của nó. Hạt nhân được tự do bỏ qua lời khuyên.

...

MADV_DONTNEED

truy cập tiếp theo của trang trong phạm vi này sẽ thành công, nhưng sẽ dẫn đến hoặc trong tải lại các nội dung bộ nhớ từ cơ bản tập tin ánh xạ (xem mmap (2)) hoặc các trang không theo yêu cầu cho ánh xạ mà không có tệp cơ bản.

...

Linux thực hiện (2.4.0) xem cuộc gọi hệ thống này nhiều hơn như một lệnh hơn là lời khuyên ...

Hoặc tôi phải munmap và remap khu vực một lần nữa?

Nó phải làm việc trên Linux và lý tưởng có hành vi tương tự trên OS X.

+0

Tôi không có cách nào để kiểm tra điều này, nhưng FWIW, [OSX] (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/madvise.2. html) trang người đàn ông không đề cập đến bất cứ điều gì về các trang 'madvise'd là số không. Phiên bản [posix] (http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_madvise.html) cũng không. Là chi phí rất lớn để tái phân bổ không gian bộ nhớ? – Collin

+0

@Collin Nó không phải là hiệu suất quá lớn khôn ngoan, nhưng tôi sẽ cần phải đình chỉ chủ đề của tôi và nếu cần thiết cập nhật con trỏ đến một bản đồ mới. Đó là mã song song hơn mà có thể đi sai ... Và tôi là loại tò mò như thế nào cuộc gọi này thực sự hoạt động. –

Trả lời

7

Có một giải pháp dễ dàng hơn nhiều cho vấn đề của bạn đó là khá cầm tay:

mmap(ptr, length, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 

Kể từ MAP_FIXED được phép thất bại vì những lý do thực hiện cụ thể khá tùy ý, té ngửa ra memset nếu nó trả MAP_FAILED sẽ được khuyến khích .

+0

Cảm ơn bạn, đây chính xác là những gì tôi đang tìm kiếm. Nó thậm chí hoạt động trên OS X. –

+3

Trong trường hợp nó không rõ ràng, ý tưởng là làm lại 'mmap()' với một địa chỉ MAP_FIXED trỏ đến một phần (hoặc toàn bộ) của bộ nhớ đã được định trước đó. Theo tài liệu, điều này sẽ ném ra các trang trước đó, và các trang mới tươi được ánh xạ. –

+0

Hiệu suất tốt hơn như thế nào là khôn ngoan? Hạt nhân vẫn cần phải zeroize trang. Vì vậy, điều này sẽ tồi tệ hơn sau đó memset trong không gian người dùng như có phí của cuộc gọi hệ thống, thực hiện logic mmap và sau đó zeroing một trang. (Mặc dù OP có thể được thực hiện với câu hỏi, tôi vẫn còn tò mò. Tôi nghĩ rằng memset sẽ vẫn là điều tốt nhất để làm ở đây) –

1

hành vi madvise Điều này chắc chắn không phải là tiêu chuẩn, vì vậy đây sẽ không được cầm tay.

Nếu phần bạn muốn không xuất hiện ở cuối bản đồ, bạn có thể lấy đi với ftruncate.Bạn sẽ phải giới thiệu thêm một bước nữa:

  1. shm_open để có một "dai dẳng" mô tả tập tin dữ liệu của bạn
  2. ftruncate với kích thước cần thiết
  3. mmap của FD rằng

Sau đó, bạn luôn có thể

  1. munmap
  2. ftruncate một cái gì đó ngắn
  3. ftruncate với độ dài thực sự bạn cần
  4. mmap lại

và sau đó là phần mà bạn "ánh xạ" sẽ là zero khởi tạo.

Nhưng cũng phải nhớ rằng hệ thống phải thực hiện zeroing của các trang. Điều này có thể hiệu quả hơn một chút so với nội dung mà trình biên dịch của bạn tạo ra cho memset, nhưng điều đó không chắc chắn.

+0

Tôi chỉ cần không có toàn bộ ánh xạ, chiều dài vẫn giữ nguyên. nếu tôi muốn đi qua 'munmap' id chỉ cần gọi' munmap', 'mmap/MAP_ANONYMOUS'. Không cần phải làm điều này phức tạp. Những gì tôi thực sự muốn không phải là đi qua một giai đoạn mà không gian VM được unmapped tạm thời, nhưng không nó nếu các trang được bẩn và lý tưởng phát hành RAM vật lý cho đến khi nó được tái sử dụng. –

+1

'munmap' được theo sau bởi' mmap' không an toàn. Nó có một điều kiện chủng tộc; phạm vi sẽ không được ánh xạ trong giây lát và một luồng khác có thể có được ánh xạ trong khu vực hoặc chỉ segfault từ cố gắng truy cập khu vực. Xem câu trả lời của tôi cho một cách tiếp cận an toàn. –

+0

@R .., câu hỏi không đề cập đến chủ đề. Nhưng chắc chắn, nếu bạn thay đổi ánh xạ dưới chân bạn, bạn phải đảm bảo rằng không có chuỗi nào khác đang truy cập nó. Nếu điều này không rõ ràng từ các ứng dụng này sẽ phải được đảm bảo bởi một số loại khóa. Nhưng điều đó vượt xa câu hỏi vì nó được đặt ra.Giải pháp của bạn có bất lợi là nó phụ thuộc vào hành vi cụ thể thực hiện. –

1

Trên Linux, bạn có thể dựa trên MADV_DONTNEED trên ánh xạ ẩn danh bằng cách không ánh xạ. Đây không phải là di động, mặc dù - madvise() chính nó không được tiêu chuẩn hóa. posix_madvise() được chuẩn hóa, nhưng POSIX_MADV_DONTNEED không không có hành vi tương tự như cờ MADV_DONTNEED Linux - posix_madvise() luôn được tư vấn và không ảnh hưởng đến ngữ nghĩa của ứng dụng.

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