Quản lý bộ nhớ thông minh với hoạt động thời gian liên tục?


18

Hãy xem xét một phân đoạn bộ nhớ (có kích thước có thể tăng hoặc thu hẹp, như tệp, khi cần) mà bạn có thể thực hiện hai thao tác cấp phát bộ nhớ cơ bản liên quan đến các khối kích thước cố định:

  • phân bổ một khối
  • giải phóng một khối được phân bổ trước đó không được sử dụng nữa.

Ngoài ra, như một yêu cầu, hệ thống quản lý bộ nhớ không được phép di chuyển xung quanh các khối được phân bổ hiện tại: chỉ mục / địa chỉ của chúng phải không thay đổi.

Thuật toán quản lý bộ nhớ ngây thơ nhất sẽ tăng bộ đếm toàn cầu (với giá trị ban đầu là 0) và sử dụng giá trị mới của nó làm địa chỉ cho phân bổ tiếp theo. Tuy nhiên, điều này sẽ không bao giờ cho phép rút ngắn phân khúc khi chỉ còn lại một số khối được phân bổ.

Cách tiếp cận tốt hơn: Giữ bộ đếm, nhưng duy trì một danh sách các khối được sắp xếp lại (có thể được thực hiện trong thời gian liên tục) và sử dụng nó làm nguồn để phân bổ mới miễn là nó không trống.

Tiếp theo là gì? Có điều gì đó thông minh có thể được thực hiện, vẫn với các ràng buộc về phân bổ và phân bổ thời gian liên tục, sẽ giữ cho phân đoạn bộ nhớ càng ngắn càng tốt?

(Mục tiêu có thể là theo dõi khối hiện không được phân bổ với địa chỉ nhỏ nhất, nhưng dường như không khả thi trong thời gian không đổi)


việc kiểm tra danh sách sẽ không còn liên tục nữa, vì danh sách có thể tăng hoặc thu hẹp do một số phân bổ / phân tách được thực hiện trước đó?
Sim

@Sim, tôi đã giả sử đó là một danh sách được liên kết và với nó, các hoạt động sẽ là , bởi vì bạn luôn chỉ làm việc với người đứng đầu. Ôi(N)
Svick

Tôi nghĩ rằng cách tiếp cận tốt hơn của bạn, LINE sẽ sử dụng lượng bộ nhớ tối ưu, nghĩa là nó sẽ không bao giờ phân bổ thêm bộ nhớ nếu có một khối miễn phí. Làm thế nào để bạn tưởng tượng cách tiếp cận thông minh của người Viking sẽ cải thiện điều đó? Bạn có nghĩa là nó nên phân bổ gần ngay từ đầu để có cơ hội tốt hơn để bạn có thể thu hẹp phân khúc sau khi thỏa thuận?
Svick

@Sim: Xin lỗi, có lẽ tôi nên sử dụng thuật ngữ stack (nhưng tôi nghĩ nó có thể gây nhầm lẫn), 'deallocate' là đẩy và 'phân bổ' là pop, hoặc trong trường hợp nó thất bại chỉ trở lại mức tăng của bộ đếm. Cả hai đều là thời gian không đổi.
Stéphane Gimenez

Bạn có những hạn chế về thời gian thực, hay bạn vẫn ổn với thời gian không đổi được khấu hao? Các câu trả lời có khả năng là khá khác nhau.
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


11

Với các khối có kích thước cố định, những gì bạn đã mô tả là một danh sách miễn phí . Đây là một kỹ thuật rất phổ biến, với vòng xoắn sau: danh sách các khối miễn phí được lưu trữ trong chính các khối miễn phí. Trong mã C, nó sẽ trông như thế này:

static void *alloc_ptr = START_OF_BIG_SEGMENT;
static void *free_list_head = NULL;

static void *
allocate(void)
{
    void *x;

    if (free_list_head == NULL) {
        x = alloc_ptr;
        alloc_ptr = (char *)alloc_ptr + SIZE_OF_BLOCK;
    } else {
        x = free_list_head;
        free_list_head = *(void **)free_list_head;
    }
    return x;
}

static void
release(void *x)
{
    *(void **)x = free_list_head;
    free_list_head = x;
}

Điều này hoạt động tốt miễn là tất cả các khối được phân bổ có cùng kích thước và kích thước đó là bội số của kích thước của một con trỏ, do đó sự liên kết được giữ nguyên. Phân bổ và phân bổ là thời gian không đổi (nghĩa là thời gian không đổi khi truy cập bộ nhớ và bổ sung cơ bản - trong một máy tính hiện đại, truy cập bộ nhớ có thể liên quan đến lỗi bộ nhớ cache và thậm chí cả bộ nhớ ảo, do đó "thời gian không đổi" có thể khá lớn). Không có chi phí bộ nhớ (không có con trỏ trên mỗi khối bổ sung hoặc những thứ tương tự; các khối được phân bổ liền kề nhau). Ngoài ra, con trỏ phân bổ chỉ đạt đến một điểm nhất định nếu tại một thời điểm, nhiều khối phải được phân bổ: vì phân bổ thích sử dụng danh sách miễn phí, con trỏ phân bổ chỉ tăng nếu không gian bên dưới con trỏ hiện tại đầy. Trong ý nghĩa đó, kỹ thuật.

Giảmcon trỏ phân bổ sau khi phát hành có thể phức tạp hơn, vì các khối miễn phí có thể được xác định một cách đáng tin cậy chỉ bằng cách làm theo danh sách miễn phí, đi qua chúng theo thứ tự không thể đoán trước. Nếu việc giảm kích thước phân khúc lớn khi có thể là quan trọng đối với bạn, bạn có thể muốn sử dụng một kỹ thuật thay thế, với nhiều chi phí hơn: giữa hai khối được phân bổ bất kỳ, bạn đặt một "lỗ". Các lỗ được liên kết với nhau với một danh sách liên kết đôi, theo thứ tự bộ nhớ. Bạn cần một định dạng dữ liệu cho một lỗ để bạn có thể xác định vị trí địa chỉ bắt đầu lỗ bằng cách biết nơi nó kết thúc và kích thước lỗ nếu bạn biết lỗ bắt đầu từ đâu trong bộ nhớ. Sau đó, khi bạn giải phóng một khối, bạn tạo một lỗ mà bạn hợp nhất với các lỗ tiếp theo và các lỗ trước đó, xây dựng lại (vẫn trong thời gian không đổi) danh sách theo thứ tự của tất cả các lỗ. Chi phí hoạt động sau đó là khoảng hai từ có kích thước con trỏ trên mỗi khối được phân bổ; nhưng, với mức giá đó, bạn có thể phát hiện một cách đáng tin cậy sự xuất hiện của "lỗ cuối cùng", tức là một dịp để giảm kích thước phân khúc lớn.

Có nhiều biến thể có thể. Một bài viết giới thiệu tốt là Phân bổ lưu trữ động: Một khảo sát và đánh giá quan trọng của Wilson et al.


4
Làm thế nào để bạn tìm thấy các lỗ gần nhất với một trang web thỏa thuận trong thời gian liên tục?
Raphael

1
Trong phương pháp thứ hai tôi mô tả, một lỗ là một tiêu đề (một cặp con trỏ, cho danh sách các lỗ) cùng với khoảng trống cho 0, một hoặc nhiều khối dữ liệu. Giữa hai khối được phân bổ bất kỳ, luôn có một lỗ, ngay cả khi đó là một lỗ siêu nhỏ chỉ bao gồm một tiêu đề lỗ. Vì vậy, việc định vị các lỗ gần nhất rất dễ dàng: chúng ở ngay trước và ngay sau khe. Tất nhiên, các lỗ nhỏ không nằm trong danh sách miễn phí (danh sách các lỗ đủ điều kiện để phân bổ). Một cách khác để xem nó là bạn thêm một tiêu đề vào mọi khối và mọi lỗ (không vi mô) (phân bổ dưới 16-bit Ms-Dos hoạt động như vậy).
Thomas Pornin

4

Câu trả lời này là về kỹ thuật quản lý bộ nhớ chung. Tôi đã bỏ lỡ rằng câu hỏi hỏi về trường hợp tất cả các khối có cùng kích thước (và được căn chỉnh).


Các chiến lược cơ bản bạn nên biết là phù hợp đầu tiên, phù hợp tiếp theo, phù hợp nhất và hệ thống bạn bè . Tôi đã viết một bản tóm tắt ngắn một lần cho một khóa học tôi đã dạy, tôi hy vọng nó có thể đọc được. Tôi chỉ đến đó một cuộc khảo sát khá đầy đủ .

Trong thực tế, bạn sẽ thấy các sửa đổi khác nhau của các chiến lược cơ bản này. Nhưng không ai trong số này là thời gian thực sự không đổi! Tôi không nghĩ điều đó có thể xảy ra trong trường hợp xấu nhất, trong khi sử dụng một lượng bộ nhớ bị giới hạn.


Thú vị, tôi phải đọc chi tiết này. Tuy nhiên, dường như các hệ thống này xử lý cụ thể việc phân bổ kích thước không cố định, đây không phải là vấn đề tôi phải đối mặt.
Stéphane Gimenez

Đúng. Xin lỗi, tôi đọc quá nhanh câu hỏi của bạn.
rgrig

Ôi(lgn)

s / khối miễn phí nhỏ nhất / khối miễn phí tại địa chỉ nhỏ nhất /
rgrig

2

Bạn có thể muốn có một cái nhìn về phân tích khấu hao và các mảng động cụ thể. Ngay cả khi các hoạt động không thực sự được thực hiện trong thời gian liên tục ở mỗi bước, về lâu dài có vẻ như đó là trường hợp.


2
Và chính xác các mảng động sẽ giúp phân bổ bộ nhớ như thế nào?
Svick

Bạn sẽ (de) phân bổ các khối của các ô liền kề bằng cách sử dụng cùng một loại thuật toán? Toàn bộ tập tin của bạn sẽ là một danh sách liên kết của các khối lớn hơn và lớn hơn.
gallais
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.