2008-10-10 72 views
69

Tôi đã nghiên cứu các tệp ánh xạ bộ nhớ cho một dự án và sẽ đánh giá cao bất kỳ suy nghĩ nào từ những người đã từng sử dụng chúng trước đây hoặc quyết định không sử dụng chúng và tại sao?Ưu điểm của tệp ánh xạ bộ nhớ là gì?

Đặc biệt, tôi lo ngại về sau, theo thứ tự quan trọng:

  • đồng thời
  • truy cập ngẫu nhiên
  • hiệu suất
  • dễ sử dụng
  • di

Trả lời

44

Tôi nghĩ rằng lợi thế thực sự là bạn giảm lượng dữ liệu sao chép được yêu cầu trên các phương pháp truyền thống để đọc tệp.

Nếu ứng dụng của bạn có thể sử dụng dữ liệu "tại chỗ" trong tệp ánh xạ bộ nhớ, nó có thể đến mà không bị sao chép; nếu bạn sử dụng cuộc gọi hệ thống (ví dụ: pread của Linux()) thì điều đó thường liên quan đến hạt nhân sao chép dữ liệu từ bộ đệm của chính nó vào không gian người dùng. Việc sao chép thêm này không chỉ mất thời gian, mà còn làm giảm hiệu quả của bộ nhớ cache của CPU bằng cách truy cập vào bản sao dữ liệu bổ sung này.

Nếu dữ liệu thực sự phải được đọc từ đĩa (như trong I/O vật lý), thì hệ điều hành vẫn phải đọc chúng, lỗi trang có thể không hiệu quả hơn so với cuộc gọi hệ thống , nhưng nếu họ không (tức là đã có trong bộ nhớ cache hệ điều hành), hiệu suất nên trong lý thuyết được tốt hơn nhiều. Mặt khác, không có giao diện không đồng bộ với các tệp ánh xạ bộ nhớ - nếu bạn cố gắng truy cập một trang không được ánh xạ, nó tạo ra lỗi trang sau đó khiến cho chuỗi chờ I/O.


Sự bất lợi rõ ràng đối với tệp ánh xạ bộ nhớ là trên hệ điều hành 32 bit - bạn có thể dễ dàng hết dung lượng địa chỉ.

+2

Trên Windows ít nhất bạn có thể bản đồ nhiều 32bit lượt xem của một tệp mmap lớn hơn - có thể hiệu quả hơn là cố gắng xử lý các tệp rất lớn bằng hàm CRT thông thường –

+0

@MarkR Bạn đã viết "sao chép thêm của mình không chỉ mất thời gian , nhưng ** giảm hiệu quả của bộ nhớ cache của CPU bằng cách truy cập vào bản sao dữ liệu bổ sung này. ** ". (** nhấn mạnh ** của tôi). Bạn có thể giải thích cách bản sao đệm bổ sung trong hạt nhân cản trở hiệu quả của bộ nhớ cache của CPU không? – Geek

+2

@Geek truy cập gấp đôi bộ nhớ nhiều gấp đôi bộ nhớ cache bị lãng phí (rất gần). – immibis

1

Đồng thời sẽ là một vấn đề. Truy cập ngẫu nhiên dễ dàng hơn Hiệu suất là tốt để tuyệt vời. Dễ sử dụng. Không tốt bằng. Tính di động - không quá nóng.

Tôi đã sử dụng chúng trên hệ thống Sun từ lâu rồi, và đó là những suy nghĩ của tôi.

18

Các tệp ánh xạ bộ nhớ có thể được sử dụng để thay thế quyền truy cập đọc/ghi hoặc để hỗ trợ chia sẻ đồng thời. Khi bạn sử dụng chúng cho một cơ chế, bạn cũng có được cơ chế khác.

Thay vì lseeking và viết và đọc xung quanh trong một tập tin, bạn ánh xạ nó vào bộ nhớ và chỉ cần truy cập vào các bit mà bạn mong đợi.

Điều này có thể rất tiện dụng và tùy thuộc vào giao diện bộ nhớ ảo có thể cải thiện hiệu suất. Cải thiện hiệu suất có thể xảy ra vì hệ điều hành giờ đây có thể quản lý "tệp I/O" cũ này cùng với tất cả truy cập bộ nhớ có lập trình khác của bạn và có thể (theo lý thuyết) tận dụng các thuật toán phân trang và do đó nó đã được sử dụng để hỗ trợ bộ nhớ ảo cho số còn lại của chương trình của bạn. Tuy nhiên, nó phụ thuộc vào chất lượng của hệ thống bộ nhớ ảo cơ bản của bạn. Giai thoại tôi đã nghe nói rằng các hệ thống bộ nhớ ảo Solaris và * BSD có thể cho thấy cải tiến hiệu suất tốt hơn so với hệ thống máy ảo của Linux - nhưng tôi không có dữ liệu thực nghiệm để sao lưu điều này. YMMV.

Đồng thời đi vào hình ảnh khi bạn xem xét khả năng của nhiều quy trình sử dụng cùng một "tệp" thông qua bộ nhớ được ánh xạ. Trong mô hình đọc/ghi, nếu hai tiến trình ghi vào cùng một vùng của tệp, bạn có thể yên tâm rằng một trong các dữ liệu của quy trình sẽ đến trong tệp, ghi đè lên dữ liệu của quy trình khác. Bạn sẽ nhận được một, hoặc khác - nhưng không phải một số intermingling lạ. Tôi phải thừa nhận rằng tôi không chắc liệu đây có phải là hành vi được bắt buộc bởi bất kỳ tiêu chuẩn nào hay không, nhưng đó là điều mà bạn có thể dựa vào khá nhiều. (Đó thực sự là câu hỏi tiếp theo về nông nghiệp!)

Trong thế giới được ánh xạ, ngược lại, hãy tưởng tượng hai quy trình vừa là "viết". Họ làm như vậy bằng cách làm "bộ nhớ cửa hàng", mà kết quả trong O/S phân trang dữ liệu ra đĩa - cuối cùng. Nhưng trong khi chờ đợi, việc viết chồng chéo có thể được dự kiến ​​sẽ xảy ra.

Đây là một ví dụ. Nói rằng tôi có hai quá trình cả hai bằng văn bản 8 byte tại offset 1024. Quy trình 1 là viết '11111111' và quá trình 2 đang viết '22222222'. Nếu họ sử dụng tập tin I/O, thì bạn có thể tưởng tượng, sâu trong O/S, có một bộ đệm đầy 1s, và một bộ đệm đầy 2s, cả hai đều hướng đến cùng một vị trí trên đĩa. Một trong số họ sẽ đến đó trước, và một giây nữa. Trong trường hợp này, cái thứ hai sẽ thắng. Tuy nhiên, nếu tôi đang sử dụng phương pháp tiếp cận tệp ánh xạ bộ nhớ, quy trình 1 sẽ chuyển một kho lưu trữ bộ nhớ 4 byte, tiếp theo là một kho lưu trữ bộ nhớ khác là 4 byte (giả sử không phải kích thước bộ nhớ tối đa).Quy trình 2 sẽ làm điều tương tự. Dựa trên thời điểm quy trình chạy, bạn có thể thấy bất kỳ điều nào sau đây:

11111111 
22222222 
11112222 
22221111 

Giải pháp này là sử dụng loại trừ lẫn nhau rõ ràng - có lẽ là ý tưởng hay trong mọi trường hợp. Bạn đã được loại dựa vào O/S để làm "điều đúng" trong trường hợp đọc/ghi tập tin I/O, anyway.

Nguyên tắc loại trừ lẫn nhau loại trừ là mutex. Đối với các tệp được ánh xạ bộ nhớ, tôi khuyên bạn nên xem xét một mutex được ánh xạ bộ nhớ, có sẵn bằng cách sử dụng (ví dụ: pthread_mutex_init().

Chỉnh sửa bằng một lần xác thực: Khi bạn đang sử dụng các tệp được ánh xạ, có sự cám dỗ để nhúng con trỏ vào dữ liệu trong tệp, trong chính tệp đó (nghĩ danh sách được liên kết được lưu trữ trong tệp được ánh xạ). Bạn không muốn làm điều đó, vì tệp có thể được ánh xạ tại các địa chỉ tuyệt đối khác nhau vào các thời điểm khác nhau hoặc trong các quy trình khác nhau. Thay vào đó, hãy sử dụng bù trừ trong tệp được ánh xạ.

43

Tôi đã sử dụng tệp ánh xạ bộ nhớ để triển khai tính năng 'tự động hoàn tất' trong khi người dùng đang nhập. Tôi có hơn 1 triệu số phần sản phẩm được lưu trữ trong một tệp chỉ mục duy nhất. Tệp có một số thông tin tiêu đề điển hình nhưng phần lớn tệp là một mảng khổng lồ các bản ghi kích thước cố định được sắp xếp trên trường khóa.

Khi tệp được lập bản đồ bộ nhớ, hãy truyền tới một mảng C kiểu struct và chúng tôi thực hiện tìm kiếm nhị phân để tìm số phần phù hợp với loại người dùng. Chỉ một vài trang bộ nhớ của tệp thực sự được đọc từ đĩa - bất kỳ trang nào được nhấn trong khi tìm kiếm nhị phân.

  • Đồng thời - Tôi gặp vấn đề về triển khai khi đôi khi bộ nhớ ánh xạ tệp nhiều lần trong cùng một không gian quy trình. Đây là một vấn đề khi tôi nhớ lại vì đôi khi hệ thống không thể tìm thấy một khối bộ nhớ ảo đủ lớn để ánh xạ tệp. Giải pháp là chỉ lập bản đồ tập tin một lần và thunk tất cả các cuộc gọi đến nó. Nhìn lại bằng cách sử dụng một dịch vụ Windows đầy đủ sẽ được mát mẻ.
  • Truy cập ngẫu nhiên - Tìm kiếm nhị phân chắc chắn là truy cập ngẫu nhiên và cực nhanh
  • Hiệu suất - Tra cứu cực kỳ nhanh. Khi người dùng gõ cửa sổ bật lên hiển thị danh sách các số phần sản phẩm phù hợp, danh sách sẽ co lại khi chúng tiếp tục nhập. Không có độ trễ đáng chú ý khi nhập.
+1

Tìm kiếm nhị phân có chậm không khi các trang được đọc trong mỗi lần thử? Hoặc là hệ điều hành đủ thông minh để đối phó với điều này một cách hiệu quả? – jjxtra

+1

Tôi giả sử sử dụng bộ nhớ ánh xạ I/O là loại lãng phí cho tìm kiếm nhị phân, vì tìm kiếm sẽ chỉ truy cập một vài khóa đơn trong các vị trí bộ nhớ tương đối xa, nhưng hệ điều hành sẽ tải trong 4k trang cho mỗi yêu cầu đó. Nhưng sau đó một lần nữa, các tập tin với các bộ phận không thay đổi nhiều, do đó, bộ nhớ cache giúp để trang trải này lên. Nhưng nói đúng, tôi tin rằng việc tìm kiếm/đọc truyền thống sẽ tốt hơn ở đây. Cuối cùng, 1 triệu là không nhiều trong những ngày này. Tại sao không chỉ giữ tất cả trong RAM? –

+2

@ lợn và PsychoDad câu trả lời ban đầu của tôi là từ năm 2008 và việc thực hiện thực tế của bộ nhớ này ánh xạ tính năng tự động hoàn thành là khoảng 2004-2005 hoặc lâu hơn. Tiêu thụ 800-1000MB bộ nhớ vật lý để tải toàn bộ tệp không phải là giải pháp tốt cho cơ sở người dùng của chúng tôi. Giải pháp bộ nhớ ánh xạ rất nhanh và hiệu quả. Nó bắt đầu và tôi nhớ nó một cách trìu mến từ những ngày đầu tiên của nhà phát triển. :) –

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