Ý nghĩa của thuật ngữ trường liên quan đến trí nhớ là gì?


100

Tôi đang đọc một cuốn sách về bộ nhớ như một khái niệm lập trình. Trong một trong những chương sau, tác giả sử dụng nhiều từ đấu trường , nhưng không bao giờ định nghĩa nó. Tôi đã tìm kiếm nghĩa của từ và cách nó liên quan đến trí nhớ, nhưng không tìm thấy gì. Dưới đây là một vài ngữ cảnh mà tác giả sử dụng thuật ngữ:

"Ví dụ tiếp theo về tuần tự hóa kết hợp một chiến lược được gọi là phân bổ bộ nhớ từ một đấu trường cụ thể ."

"... điều này rất hữu ích khi xử lý rò rỉ bộ nhớ hoặc khi phân bổ từ một đấu trường cụ thể ."

"... nếu chúng ta muốn phân bổ ký ức thì chúng ta sẽ phân bổ toàn bộ đấu trường ."

Tác giả sử dụng thuật ngữ này hơn 100 lần trong một chương. Định nghĩa duy nhất trong bảng thuật ngữ là:

phân bổ từ đấu trường - Kỹ thuật phân bổ đấu trường trước và sau đó quản lý việc phân bổ / phân bổ giao dịch trong đấu trường bằng chính chương trình (thay vì sau đó bởi trình quản lý bộ nhớ tiến trình); được sử dụng để nén và tuần tự hóa các cấu trúc và đối tượng dữ liệu phức tạp hoặc để quản lý bộ nhớ trong các hệ thống quan trọng về an toàn và / hoặc khả năng chịu lỗi.

Bất cứ ai có thể xác định đấu trường cho tôi với những bối cảnh này?


Tên cuốn sách là gì?
yaobin

1
@yaobin Bộ nhớ như một khái niệm lập trình trong C và C ++ của Frantisek Franek.
Nocturno

Câu trả lời:


109

Đấu trường chỉ là một phần bộ nhớ lớn, liền kề mà bạn phân bổ một lần và sau đó sử dụng để quản lý bộ nhớ theo cách thủ công bằng cách phân phát các phần của bộ nhớ đó. Ví dụ:

char * arena = malloc(HUGE_NUMBER);

unsigned int current = 0;

void * my_malloc(size_t n) { current += n; return arena + current - n; }

Vấn đề là bạn có toàn quyền kiểm soát cách cấp phát bộ nhớ hoạt động. Điều duy nhất nằm ngoài sự kiểm soát của bạn là lệnh gọi thư viện đơn cho phân bổ ban đầu.

Một trường hợp sử dụng phổ biến là mỗi đấu trường chỉ được sử dụng để cấp phát các khối bộ nhớ có một kích thước cố định duy nhất. Trong trường hợp đó, bạn có thể viết các thuật toán khai hoang rất hiệu quả. Một trường hợp sử dụng khác là có một đấu trường cho mỗi "nhiệm vụ" và khi hoàn thành nhiệm vụ, bạn có thể giải phóng toàn bộ đấu trường trong một lần và không cần phải lo lắng về việc theo dõi các phân bổ riêng lẻ.

Mỗi kỹ thuật đó đều rất chuyên biệt và thường chỉ hữu ích nếu bạn biết chính xác mình đang làm gì và tại sao việc phân bổ thư viện bình thường là không đủ tốt. Lưu ý rằng một trình cấp phát bộ nhớ tốt sẽ tự nó làm được rất nhiều điều kỳ diệu và bạn cần một lượng bằng chứng phù hợp cho thấy điều đó chưa đủ tốt trước khi bắt đầu tự xử lý bộ nhớ.


25
Đó là một câu trả lời hay, nhưng hãy xem xét việc xóa hoặc sửa đổi đoạn cuối cùng. Bạn thực sự không cần bất kỳ bằng chứng nào cả. Bất cứ khi nào bạn biết mình sẽ sử dụng bộ nhớ như thế nào , bạn biết nhiều hơn một bộ cấp phát có mục đích chung "tốt" và nếu bạn sử dụng kiến ​​thức này, bộ cấp phát tùy chỉnh của bạn sẽ luôn chiến thắng. Người phân bổ không phải là ma thuật. Đấu trường sẽ hữu ích nếu bạn có nhiều vật phẩm chết cùng một thời điểm, được xác định rõ về thời gian. Đó là khá nhiều tất cả những gì bạn cần biết. Nó không phải là khoa học tên lửa.
Andreas Haferburg

11
@AndreasHaferburg: Trình cấp phát bộ nhớ từ thư viện tiêu chuẩn tự động có lợi thế lớn so với việc bạn tự viết tùy chỉnh, cụ thể là bạn không phải viết / kiểm tra / gỡ lỗi / bảo trì, v.v. Ngay cả khi bạn chắc chắn không có bằng chứng nào cho thấy bạn có thể cải thiện hiệu suất bằng cách quản lý phân bổ của riêng bạn, bạn vẫn cần bằng chứng tốt trước khi quyết định rằng cải tiến này đáng để đánh đổi.
ruakh

17
@ruakh Tôi không thích cái tâm lý sùng bái hàng hóa được lặp đi lặp lại hàng triệu lần ở khắp mọi nơi như là "sự khôn ngoan". "Các vị thần của C ++ đã ban cho chúng ta, vì vậy chúng ta phải sử dụng nó." Và tôi thích nhất: "Đó là phép thuật." Không, nó không phải là ma thuật. Nó chỉ là một thuật toán đơn giản đến mức ngay cả máy tính cũng có thể chạy nó. Trong cuốn sách của tôi, điều đó khá xa vời với ma thuật. Tôi đoán: Bạn đánh giá thấp mức độ ảnh hưởng của phân bổ bộ nhớ đối với hiệu suất và đánh giá quá cao mức độ phức tạp của các đấu trường. Liệu hiệu suất có quan trọng hơn thời gian của nhà phát triển hay không là một quyết định kinh doanh mà hơi vô nghĩa khi thảo luận trên SO.
Andreas Haferburg

8
@AndreasHaferburg: Chắc chắn rồi, tcmalloc sử dụng một số thuật toán cụ thể và ý tưởng đằng sau nó đủ dễ giải thích, nhưng việc triển khai vẫn phức tạp và không tầm thường. Quan trọng nhất, nó yêu cầu kiến ​​thức về nền tảng cụ thể để sắp xếp đúng thứ tự bộ nhớ. Tôi sử dụng "ma thuật" cho những thứ mà người dùng không thể viết dễ dàng (như mutex hiệu quả, hoặc tcmalloc, hoặc tên kiểu của lambda), hoặc chỉ với các tác phẩm anh hùng cực độ (như std :: function); Ý tôi không phải là "không thể hiểu được".
Kerrek SB

12
@AndreasHaferburg: Và lời khuyên cuối cùng của tôi không phải là nói quá nhiều rằng về nguyên tắc khó có thể "biết rõ hơn mặc định", mà là chi phí duy trì một giải pháp tùy chỉnh cao (ai đó phải viết nó, ghi lại nó, lấy nó đúng, và người khác phải sửa lỗi và mọi người phải xem xét và xác minh lại các giả định ban đầu là chênh lệch sử dụng) và bạn cần bằng chứng để biện minh cho chi phí đó.
Kerrek SB

10

Tôi sẽ đi với câu trả lời này như một câu trả lời có thể.

•Memory Arena (also known as break space)--the area where dynamic runtime memory is stored. The memory arena consists of the heap and unused memory. The heap is where all user-allocated memory is located. The heap grows up from a lower memory address to a higher memory address.

Tôi sẽ thêm các từ đồng nghĩa của Wikipedia : vùng, khu vực, đấu trường, khu vực hoặc bối cảnh bộ nhớ.

Về cơ bản, đó là bộ nhớ bạn nhận được từ hệ điều hành và chia ra, sau đó có thể được giải phóng tất cả cùng một lúc. Ưu điểm của điều này là các cuộc gọi nhỏ lặp đi lặp lại malloc()có thể tốn kém (Mọi cấp phát bộ nhớ đều có chi phí hiệu suất: thời gian cần thiết để cấp phát bộ nhớ trong không gian địa chỉ logic của chương trình của bạn và thời gian cần thiết để gán không gian địa chỉ đó cho bộ nhớ vật lý) nơi như thể bạn biết một công viên bóng, bạn có thể có cho mình một bộ nhớ lớn sau đó đưa nó cho các biến của bạn như / cách bạn cần.


5

Hãy nghĩ về nó như một từ đồng nghĩa với 'đống'. Thông thường, quy trình của bạn chỉ có một heap / Arena và tất cả việc phân bổ bộ nhớ sẽ xảy ra từ đó.

Tuy nhiên, đôi khi bạn gặp phải tình huống mà bạn phải nhóm một loạt các phân bổ lại với nhau (ví dụ: cho hiệu suất, để tránh phân mảnh, v.v.). Trong trường hợp đó, tốt hơn nên phân bổ một đống / đấu trường mới, và sau đó đối với bất kỳ phân bổ nào, bạn có thể quyết định phân bổ từ đống nào.

Ví dụ, bạn có thể có một hệ thống hạt trong đó rất nhiều đối tượng có cùng kích thước thường xuyên được phân bổ và phân bổ. Để tránh phân mảnh bộ nhớ, bạn có thể phân bổ từng hạt từ một đống chỉ được sử dụng cho các hạt đó và tất cả các phân bổ khác sẽ đến từ heap mặc định.


5

Từ http://www.bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html :

Thư viện chia sẻ libc.so.x chứa thành phần glibc và mã heap nằm bên trong nó. Việc triển khai heap hiện tại sử dụng nhiều heap con độc lập được gọi là đấu trường. Mỗi đấu trường có mutex riêng để bảo vệ đồng thời. Vì vậy, nếu có đủ các đấu trường trong một 'đống quy trình và một cơ chế để phân phối các truy cập đống' luồng 'đồng đều giữa chúng, thì khả năng tranh chấp cho các mutexes sẽ là tối thiểu. Nó chỉ ra rằng điều này hoạt động tốt cho phân bổ. Trong malloc (), một bài kiểm tra được thực hiện để xem liệu mutex cho đấu trường mục tiêu hiện tại cho luồng hiện tại có miễn phí hay không (trylock). Nếu vậy thì đấu trường hiện đã bị khóa và việc phân bổ sẽ được tiến hành. Nếu mutex bận thì lần lượt từng đấu trường còn lại được thử và sử dụng nếu mutex không bận. Trong trường hợp không khóa được đấu trường nào mà không bị chặn, một đấu trường mới sẽ được tạo. Đấu trường này theo định nghĩa vẫn chưa bị khóa, vì vậy việc phân bổ hiện có thể tiếp tục mà không bị chặn. Cuối cùng, ID của đấu trường được sử dụng lần cuối bởi một luồng được giữ lại trong bộ lưu trữ cục bộ của luồng và sau đó được sử dụng làm đấu trường đầu tiên để thử khi malloc () được gọi tiếp theo bởi luồng đó. Do đó, tất cả các cuộc gọi đến malloc () sẽ tiếp tục mà không bị chặn.

Bạn cũng có thể tham khảo liên kết này:

http://www.codeproject.com/Articles/44850/Arena-Allocator-DTOR-and-Embedded-Preallocated-Buf


3
FYI khi đăng liên kết bạn nên đăng tóm tắt để nếu bài viết liên kết mất đi bài viết của bạn vẫn hữu ích.
stonemetal

5
Đây dường như là bản sao-dán từ bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html Vui lòng ghi có nguồn của bạn khi bạn sử dụng nguyên văn.
jscs 11/10/12
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.