2009-04-07 53 views
12

Tôi có một chương trình mà tôi muốn lưu trữ dữ liệu nhất định (khối được phân bổ động), trên đĩa để giảm mức sử dụng bộ nhớ và độ bền.Phân bổ bộ nhớ động dựa trên đĩa

Suy nghĩ đầu tiên của tôi là viết trình phân bổ tùy chỉnh của riêng tôi đã quản lý nội dung tệp trên đĩa, nhưng tôi cũng muốn xem các lựa chọn thay thế nào.

Tôi đã xem xét các bộ phân bổ bộ nhớ tùy chỉnh và các chủ đề về tuần tự hóa đối tượng nhưng có những khác biệt tinh tế, cả tốt lẫn xấu, khi điều chỉnh các nguyên tắc đó để quản lý không gian địa chỉ của tệp.

Trong tình huống này:

  1. Memory được truy cập chỉ qua IO (đọc/ghi) chức năng hơn là trực tiếp

  2. Không đối tượng (phương pháp/con trỏ) được lưu trữ, chỉ có dữ liệu.

  3. Kích thước của một tập tin không phải là tĩnh, vì vậy nó sẽ tăng trưởng khi cần thiết chứ không phải là lớn và tĩnh

  4. Đối với công dụng của tôi, nó có thể chấp nhận để tái bản đồ con trỏ hiện sau khi chống phân mảnh

Do dữ liệu không có kích thước cố định, hầu hết các triển khai cơ sở dữ liệu dường như không phù hợp.

Tôi hỏi, cách tiếp cận tốt nhất cho vấn đề này là gì? Tôi có nên thực hiện một bộ cấp phát bộ nhớ đơn giản mà xử lý một tập tin như đống?

Để tham khảo, hãy sử dụng C++ trên thiết bị được nhúng.


Chỉnh sửa: Tôi đã triển khai trình quản lý bộ nhớ của riêng mình sử dụng phân bổ bộ nhớ buddy và kích thước khối quyền hạn của hai. Tôi hài lòng rằng nó là chính xác và không bị rò rỉ, kết hợp các khối miễn phí, và có thể làm một 'ngăn chặn thế giới' chống phân mảnh.

Vấn đề là, như mong đợi, có khá nhiều phân mảnh bên trong và bên ngoài. Tôi không phải là một chuyên gia trong lĩnh vực này và mặc dù tôi thấy nó hấp dẫn (tôi vẫn còn là một sinh viên), tôi tự hỏi nếu có bất kỳ triển khai khác đã làm điều tương tự hoặc tương tự? Chắc chắn tôi không thể là người duy nhất?


Một số chủ đề hữu ích nhưng cho đến nay không tương thích là:

mmap tbh tôi havent đã qua sử dụng mmap nhưng, nó đề cập đến tập tin IO, nhưng không phải là quản lý không gian địa chỉ tập tin.

BOOST:serialization Tôi có một (có lẽ không được điều chỉnh) miễn cưỡng sử dụng thư viện tăng cường vào lúc này.

STXXL địa chỉ bộ nhớ kích thước Thú vị nhưng doesnt biến phân bổ

Doug Lea Memory Allocator Có những hiểu biết rất tốt vào các vấn đề với allocators bộ nhớ, nhưng tôi không ở một vị trí để thử và làm cho thực hiện của riêng tôi

Trả lời

8

Hai mục tiêu của bạn là giảm mức sử dụng bộ nhớ và duy trì dữ liệu của bạn. Điều đó chắc chắn giống như một công việc cho một cơ sở dữ liệu . Nhưng sau đó bạn nói

Vì dữ liệu không phải là kích thước cố định , hầu hết việc triển khai cơ sở dữ liệu dường như không phù hợp.

Tôi nghĩ rằng bạn sẽ quan tâm đến việc distinctive feature of SQLite này (một cơ sở dữ liệu đa nền tảng rất nhẹ với mã nguồn miền công cộng):

Variable-length hồ sơ

...

SQLite, ngược lại, chỉ sử dụng dung lượng đĩa thực sự cần thiết để lưu trữ thông tin liên tiếp. Nếu bạn lưu trữ một ký tự đơn lẻ trong cột VARCHAR (100), thì chỉ một byte không gian đĩa được sử dụng . (Trên thực tế hai byte - có một số overhead vào đầu mỗi cột để ghi datatype và dài.)

Nó cũng là một good choice for embedded development:

các thiết bị nhúng và ứng dụng

Do cơ sở dữ liệu SQLite yêu cầu ít hoặc không có quyền quản trị, SQLite là một lựa chọn tốt cho các thiết bị hoặc dịch vụ phải hoạt động không cần giám sát và không có sự hỗ trợ của con người . SQLite phù hợp với để sử dụng trong điện thoại di động, PDA, hộp số set-top và/hoặc thiết bị. Nó cũng hoạt động tốt như một cơ sở dữ liệu được nhúng trong các ứng dụng khách hàng có thể tải xuống.

+0

+1, để đề cập đến SQLite, một thư viện tuyệt vời của nó và tôi sử dụng nó rất nhiều. Nhưng SQLite không xử lý các mẫu sử dụng mà tôi sau khi tốt. Đó là số lượng lớn dữ liệu có kích thước tùy ý hoàn toàn (không phải bản ghi cố định). Khi kích thước tệp phát triển (GB +), việc triển khai SQLite sẽ bị ngừng lại. – Akusete

+0

@Akusete làm điều đó? Tôi nhớ nhập một bãi chứa en.wikipedia trong cơ sở dữ liệu sqlite và nó vẫn hoạt động khá tốt ... – CAFxX

+0

@CAFxX: Câu hỏi hay. Đây là một tuyên bố giai thoại dựa trên việc sử dụng SQLite với các lược đồ phức tạp (100GB +) rất lớn. Tôi giả định rằng vì tôi chỉ cần lưu trữ các đốm màu, có cơ sở dữ liệu sql (thậm chí sqlite) sẽ phải chịu tải không cần thiết và tối ưu phụ, nhưng tôi cho rằng trong tầm nhìn là một giả định yếu. Ngoài ra, tôi đã là sinh viên cố gắng để thực hiện một công cụ cơ sở dữ liệu, do đó, sao lưu lưu trữ blob của nó với SQLite có vẻ giống như một cảnh sát. :) – Akusete

1

Đối với các thiết bị nhúng Tôi chắc chắn sẽ thực hiện một cách đơn giản thay vì sử dụng một cơ sở dữ liệu. Tập tin trực tiếp IO tránh một số chi phí của cơ sở dữ liệu. Và tài nguyên thường bị giới hạn trong môi trường nhúng.

Ý tưởng của bạn viết bộ cấp phát bộ nhớ có lẽ là cách tốt nhất. Nó sẽ cung cấp một số loại lớp API để cô lập việc quản lý bộ nhớ dựa trên tập tin càng nhiều càng tốt từ phần còn lại của ứng dụng của bạn. Bằng cách đó nó sẽ được dễ dàng để trao đổi ra (không có ý định chơi chữ) cho một thực hiện khác nhau sau này và do đó tối ưu hóa nếu nhu cầu phát sinh.

+0

Cảm ơn bạn đã nhập. Tôi đã chỉnh sửa câu hỏi của mình với một số chi tiết tiếp theo – Akusete

1

Tôi chắc chắn sẽ sử dụng mmap cho I/O. Điều này sẽ giúp dễ dàng truy cập trực tiếp dữ liệu và chuyển sang đĩa khi cần. Điều duy nhất bạn sẽ phải kiểm soát là nơi tệp được ánh xạ trong không gian địa chỉ, vì vậy bạn có thể di chuyển nó xung quanh.

Một khả năng để quản lý bộ nhớ là tạo một tệp khác cho từng đối tượng và sử dụng phân mảnh cấp tệp hệ thống thay vì tự thực hiện nó. Bạn không bao giờ đề cập đến hệ điều hành/tập tin hệ thống bạn đang sử dụng, nhưng nếu nó đã có chống phân mảnh trực tuyến, tôi sẽ sử dụng nó. Nếu bạn đang sử dụng Linux và có thể sử dụng XFS, bạn có thể sử dụng xfs_fsr. Tôi mong đợi sự phân mảnh tập tin hệ thống sẽ được tối ưu hóa cao và sẽ tốn ít công sức hơn là tự thực hiện trong một tệp lớn.

+0

Tôi nên tự làm quen với mmap, khi bạn ánh xạ vùng không gian địa chỉ để bạn 'sở hữu' tất cả (và phải tự quản lý) hoặc bạn có thể sử dụng/xóa mới (Tôi không thể thấy làm thế nào mà sẽ làm việc) để phân bổ các đối tượng? Vấn đề của tôi là tôi muốn tạo nhiều đối tượng nhỏ, tệp 1per có quá nhiều chi phí. – Akusete

+0

Khi bạn sử dụng mmap, bạn phải tự mình quản lý nó.Nếu bạn muốn sử dụng mới và xóa, bạn sẽ phải quá tải các toán tử đó để phân bổ vào vùng mmap-ed bằng cách sử dụng một số thuật toán phân bổ. Nó có lẽ sẽ dễ dàng nhất để chỉ sửa đổi dlmalloc. – Zifre

8

Tôi đã triển khai trình quản lý bộ nhớ của riêng mình sử dụng phân bổ bộ nhớ bạn bè và kích thước khối quyền hạn của hai. Tôi hài lòng nó là chính xác và đã không bị rò rỉ, thanesses khối miễn phí và có thể làm một 'ngăn chặn thế giới' chống phân mảnh.

Đó là bước đầu tiên tuyệt vời. Một khi bạn có một bộ cấp phát bộ nhớ tùy chỉnh làm việc, bạn có thể tất nhiên làm tốt hơn!

Vấn đề là, như mong đợi có khá nhiều nội bộ (sức mạnh của 2 khối) và phân mảnh bên ngoài. Tôi không phải là một chuyên gia trong lĩnh vực này và mặc dù tôi tìm thấy nó facinating (tôi vẫn còn là một sinh viên), tôi tự hỏi nếu có bất kỳ triển khai khác đã làm điều tương tự hoặc tương tự? Chắc chắn tôi không thể là người duy nhất?

Sức mạnh của hai là cách tiếp cận chung. Tuy nhiên, lưu ý rằng điều này có thể không phải là tốt nhất vì mô hình phân bổ của bạn có thể không theo cùng tiến trình hình học. Trong trường hợp này, tốt nhất là nên kiểm tra càng nhiều càng tốt và xem kích thước khối nào được phân bổ nhiều nhất và tối ưu hóa cho phù hợp.

Tôi cũng muốn đề xuất điều này một bài viết tuyệt vời của Andrei Alexandrescu và Emery Berger về chủ đề phân bổ bộ nhớ: Policy-Based Memory Allocation và tác phẩm thứ hai cụ thể: The Hoard Memory Allocator.

Nếu có thể, hãy xem các tham chiếu được đề cập ở cuối bài viết đó. Họ cũng có thể cung cấp thông tin chi tiết bổ sung.

1

Từ những gì tôi hiểu bạn cần hệ thống tệp chứ không phải hệ thống phân bổ bộ nhớ. Ban đầu, trong các hệ thống nhúng, cấp phát bộ nhớ động trong đĩa là một thuật ngữ mâu thuẫn. Đĩa, hoặc đĩa cứng hoặc thiết bị flash, được sử dụng để lưu trữ liên tục khác nhiều so với bộ nhớ.Nó không chỉ là cách bạn truy cập nó, nhưng thực tế là lưu trữ đĩa không phải là 100% đáng tin cậy. Khi ghi vào đĩa, bạn cần có một thuật toán để tránh các thành phần xấu. Bạn có nghĩ về điều này hoặc bạn có thể xem xét lỗi đĩa của bạn miễn phí?

Hệ thống tệp sẽ xử lý cả vấn đề phân bổ không gian và các vấn đề về ngành xấu. FAT thường được sử dụng trong các thiết bị nhúng. Mặc dù hiệu suất phân mảnh của FAT khá kém, điều này đã không ngăn nó được sử dụng trong nhiều thiết bị nhúng. Hầu hết các thiết bị dựa trên flash thực sự sử dụng FAT.

Dù sao, tôi khuyên bạn nên bắt đầu với những gì bạn có bây giờ: hệ điều hành của bạn (nếu bạn sử dụng bất kỳ) và trình điều khiển cho đĩa của bạn. Điều tra nếu một giải pháp phù hợp đã được hỗ trợ từ những giải pháp này. Ngoài ra, hãy nhớ rằng các thiết bị nhúng khó gỡ lỗi hơn - nếu bạn đặt để triển khai các thuật toán của riêng bạn, hãy chờ đợi thời gian phát triển dài hơn.

+0

Thành thật mà nói, tôi chưa bao giờ nghĩ về hầu hết những vấn đề đó. Tôi chỉ nhìn vào đĩa như một không gian địa chỉ (chậm) khác để có cách của tôi với :). Tôi hiện đang sử dụng tiêu chuẩn C + + (tập tin dòng IO), do đó, nó không hoạt động phụ thuộc vào hệ thống. – Akusete

+0

Bạn cần phải lo lắng về việc có một trình điều khiển đáng tin cậy cho đĩa của bạn. Sau đó mọi thứ khác theo sau. – kgiannakakis

0

Tôi nghĩ rằng bạn sẽ có ít phân mảnh nội bộ hơn với trình phân bổ heap đơn giản. Bạn chỉ cần phân bổ số lượng bộ nhớ bạn thực sự sử dụng (cộng với chi phí cho tiêu đề). Nếu bạn đã từ chức để thực hiện việc nén thế giới, bạn có thể kết hợp điều này với phân bổ trường mới và phân bổ một trường mới (lớn hơn) và sao chép tất cả các khối trực tiếp của bạn vào đấu trường mới.

2

Gần đây, tôi đã mã hóa một lớp heap ảo cho sự cố sử dụng bộ nhớ cao mà tôi có. Mã này được LGPL'ed và được lưu trữ tại code.google.com tại địa chỉ:

http://code.google.com/p/kgui/source/browse/trunk/vheap.cpp

http://code.google.com/p/kgui/source/browse/trunk/vheap.h

Về cơ bản nó hoạt động như sau:

1) Xác định kích thước khối và số lượng khối để lại trong bộ nhớ và tên tệp cho bộ nhớ đệm vào hệ thống tệp. Trong trường hợp sử dụng của tôi, tôi có 200 khối bộ nhớ 1MB bất cứ lúc nào.

2) Sau đó, hãy gọi Phân bổ để đặt trước một đoạn "bộ nhớ ảo". Bạn được trả về một 8byte "xử lý" vào bộ nhớ. Bạn có thể phân bổ các khối lớn hơn kích thước khối nếu muốn.

3) Để ghi vào "vùng heap ảo", có chức năng ghi nơi bạn vượt qua "xử lý", trỏ đến dữ liệu và kích thước của dữ liệu.

4) Để đọc từ "vùng heap ảo", có chức năng đọc trong đó bạn chuyển "xử lý", con trỏ đến đích và kích thước dữ liệu cần đọc.

Mã tự động xử lý trao đổi giữa những gì có trong bộ nhớ và những gì được lưu trữ trên đĩa. Nó thực sự khá đơn giản.

3

Tùy chọn tốt nhất của bạn sẽ nhanh chóng key-value store. Lợi thế so với RDBMS là bạn sẽ không cần tất cả các chi phí của cơ sở dữ liệu.

0

Tôi sẽ lặp lại kgiannakakis - những gì bạn mô tả là hệ thống tệp chứ không phải hệ thống quản lý bộ nhớ.

Vì tất cả truy cập của bạn đều thông qua các chức năng I/O, không cần thiết đối tượng của bạn tiếp giáp trên đĩa. Thay vì đặt từng đối tượng vào một khối kích thước động, hãy chia đối tượng thành nhiều khối có kích thước cố định. Các khối có thể được đặt ở bất cứ đâu, tất cả những gì bạn cần là một cách để liên kết chúng với nhau. Các hàm I/O của bạn sẽ chia nhỏ và kết hợp các khối khi cần thiết.

0

Hmmh. Điều này nghe có vẻ giống như một trường hợp sử dụng rất phổ biến cho BDB (Berkeley DB). Đó là một thư viện chất lượng sản xuất hiệu quả làm các "cơ sở dữ liệu" khóa-giá trị liên tục (~ = bảng với các DB khác), nguồn mở và tất cả.

Tôi không nghĩ rằng DB quan hệ (SQL) có ý nghĩa nhiều, nhưng bdb et al (gnu db và tôi chắc chắn có những người khác) chắc chắn không.

0

Bạn có thể xem các cơ sở được cung cấp bởi Boost.Interprocess, đặc biệt là xem xét các cơ sở tệp được ánh xạ bộ nhớ được quản lý.

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