Ưu điểm của tệp ánh xạ bộ nhớ là gì?


89

Tôi đang 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 đã sử dụng chúng trước đây hoặc quyết định không sử dụng chúng, và tại sao?

Đặc biệt, tôi quan tâm đến những điều 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
  • tính di động

Câu trả lời:


56

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

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ớ, thì nó có thể đến mà không bị sao chép; nếu bạn sử dụng lệnh gọi hệ thống (ví dụ: pread ()) của Linux thì điều đó thường liên quan đến việc 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ỉ tốn thời gian mà còn làm giảm hiệu quả của bộ nhớ đệm của CPU khi 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 trong đó, lỗi trang có lẽ không hiệu suất tốt hơn lệnh gọi hệ thống, nhưng nếu chúng không (tức là đã có trong bộ nhớ cache của hệ điều hành), hiệu suất về lý thuyết sẽ 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 được ánh xạ bộ nhớ - nếu bạn cố gắng truy cập vào một trang không được ánh xạ vào, nó sẽ tạo ra lỗi trang sau đó khiến chuỗi chờ I / O.


Nhược điểm rõ ràng đối với các tệp được ánh xạ bộ nhớ là trên hệ điều hành 32-bit - bạn có thể dễ dàng sử dụng hết không gian địa chỉ.


4
Trên Windows ít nhất bạn có thể ánh xạ nhiều quan điểm 32bit của một file mmap lớn hơn - có thể hơn efficent hơn là cố gắng để đối phó với các tập tin rất lớn sử dụng chức năng CRT thường xuyên
Martin Beckett

@MarkR Bạn đã viết "việc sao chép thêm của anh ấy không chỉ mất thời gian mà còn làm giảm hiệu quả của bộ nhớ đệm của CPU khi 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ể vui lòng giải thích cách sao chép bộ đệm bổ sung trong hạt nhân cản trở hiệu quả của bộ nhớ đệm của CPU không?
Geek

4
@Geek truy cập gấp đôi bộ nhớ = lãng phí gấp đôi bộ nhớ cache (rất gần).
user253751

49

Tôi đã sử dụng tệp ánh xạ bộ nhớ để triển khai tính năng 'tự động hoàn thành' trong khi người dùng đang nhập. Tôi có hơn 1 triệu số bộ 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 của tệp là một mảng khổng lồ các bản ghi có kích thước cố định được sắp xếp trên trường khóa.

Trong thời gian chạy, tệp được ánh xạ bộ nhớ, truyền sang mảng Ckiểu structvà chúng tôi thực hiện tìm kiếm nhị phân để tìm số phần phù hợp như kiểu người dùng. Chỉ một số trang bộ nhớ của tệp thực sự được đọc từ đĩa - bất kỳ trang nào được nhấn trong quá trình tìm kiếm nhị phân.

  • Đồng thời - Tôi đã gặp sự cố triển khai trong đó đôi khi bộ nhớ sẽ á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 đề như tôi nhớ lại vì đôi khi hệ thống không thể tìm thấy khối bộ nhớ ảo đủ lớn còn trống để ánh xạ tệp tới. Giải pháp là chỉ ánh xạ tệp một lần và thu nhận tất cả các lệnh gọi đến tệp đó. Nhìn lại việc sử dụng một dịch vụ Windows hoàn chỉnh sẽ rất tuyệt.
  • 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à nhanh như chớp
  • Hiệu suất - Việc tra cứu cực kỳ nhanh chóng. Khi người dùng nhập, một cửa sổ bật lên sẽ hiển thị danh sách số bộ phận sản phẩm phù hợp, danh sách sẽ thu hẹp lại khi họ tiếp tục nhập. Không có độ trễ đáng chú ý trong khi gõ.

1
Tìm kiếm nhị phân sẽ không chậm vì các trang được đọc trong mỗi lần thử? Hay hệ điều hành có đủ thông minh để giải quyết vấn đề này một cách hiệu quả?
jjxtra

1
Tôi cho rằng việc sử dụng I / O được ánh xạ trong bộ nhớ là hơi lãng phí cho tìm kiếm nhị phân, vì tìm kiếm sẽ chỉ truy cập vào một vài khóa đơn ở 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ư vậy. Nhưng một lần nữa, tệp có các phần không thay đổi nhiều, vì vậy bộ nhớ cache sẽ giúp che đậy điều này. Nhưng nói đúng ra, tôi tin rằng tìm kiếm / đọc truyền thống sẽ tốt hơn ở đây. Cuối cùng, 1 triệu không phải là nhiều trong những ngày này. Tại sao không chỉ giữ tất cả trong RAM?
con lợn

5
@the swine và PsychoDad Câu trả lời ban đầu của tôi là từ năm 2008 và việc triển khai thực tế tính năng tự động hoàn thành được ánh xạ bộ nhớ này vào khoảng năm 2004-2005 hoặc lâu hơn. Tiêu tốn 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 ánh xạ bộ nhớ rất nhanh và hiệu quả. Nó rất thú vị và tôi nhớ nó rất thú vị từ những ngày đầu là nhà phát triển cơ sở của tôi. :)
Brian Ensink

@BrianEnsink: ok, có lý. tôi đã không mong đợi mỗi mục nhập nhiều như 1kB. thì tất nhiên cách tiếp cận phân trang sẽ hiệu quả hơn. tốt đẹp :)
the swine

22

Các tệp được ánh xạ trong 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 nhận được cơ chế kia.

Thay vì tìm kiếm và ghi và đọc xung quanh một tệp, bạn ánh xạ nó vào bộ nhớ và chỉ cần truy cập các bit ở nơi 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. Việc cải thiện hiệu suất có thể xảy ra vì hệ điều hành hiện có thể quản lý "tệp I / O" trước đây cùng với tất cả quyền truy cập bộ nhớ có lập trình khác của bạn và (về lý thuyết) có thể tận dụng các thuật toán phân trang, v.v. mà nó đã được sử dụng để hỗ trợ bộ nhớ ảo cho phần 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 bên dưới của bạn. Những giai thoại tôi đã nghe nói rằng hệ thống bộ nhớ ảo Solaris và * BSD có thể cải thiện hiệu suất tốt hơn hệ thống VM 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 xuất hiện khi bạn xem xét khả năng có 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 quá trình được ghi vào cùng một vùng của tệp, bạn có thể khá yên tâm rằng một trong các dữ liệu của quá trình sẽ đến tệp, ghi đè lên dữ liệu của quá trình kia. Bạn sẽ nhận được cái này hoặc cái kia - nhưng không phải là một số xen kẽ kỳ 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 yêu cầu bởi bất kỳ tiêu chuẩn nào hay không, nhưng đó là điều bạn có thể dựa vào khá nhiều. (Đây thực sự là câu hỏi tiếp theo rất hay!)

Ngược lại, trong thế giới được ánh xạ, hãy tưởng tượng hai quá trình đều "viết". Họ làm như vậy bằng cách thực hiện "lưu trữ bộ nhớ", dẫn đến cuối cùng là O / S phân trang dữ liệu ra đĩa. Nhưng trong thời gian chờ đợi, việc ghi chồng chéo có thể xảy ra.

Đây là một ví dụ. Giả sử tôi có hai quy trình đều ghi 8 byte ở khoảng cách 1024. Quy trình 1 đang viết '11111111' và quy trình 2 đang viết '22222222'. Nếu họ sử dụng tệp 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 đích đầu tiên, và người còn lại trong giây. Trong trường hợp này, người thứ hai 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 đến một bộ nhớ lưu trữ 4 byte, tiếp theo là một bộ nhớ lưu trữ 4 byte khác (giả sử đó không phải là kích thước lưu trữ 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 các quy trình chạy, bạn có thể thấy bất kỳ thông tin nào sau đây:

11111111
22222222
11112222
22221111

Giải pháp cho điều này là sử dụng loại trừ lẫn nhau rõ ràng - có lẽ là một ý tưởng hay trong mọi trường hợp. Dù sao thì bạn cũng dựa vào O / S để làm "điều đúng đắn" trong trường hợp đọc / ghi tệp I / O.

Nguyên thủy loại trừ lẫn nhau phân loại là mutex. Đối với các tệp được ánh xạ bộ nhớ, tôi khuyên bạn nên xem 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 gotcha: Khi bạn đang sử dụng các tệp được ánh xạ, có một sự cám dỗ để nhúng con trỏ đến dữ liệu trong tệp, trong chính tệp đó (hãy nghĩ đến 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 các hiệu số trong tệp được ánh xạ.


1

Đồng tiền sẽ là một vấn đề. Truy cập ngẫu nhiên dễ dàng hơn Hiệu suất từ ​​tốt đến tốt. 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ệ Mặt trời từ lâu, và đó là những suy nghĩ của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.