Phân bổ heap tùy chỉnh


9

Hầu hết các chương trình có thể khá ngẫu nhiên về phân bổ heap, thậm chí đến mức các ngôn ngữ lập trình chức năng thích phân bổ các đối tượng mới hơn là sửa đổi các đối tượng cũ và để người thu gom rác lo lắng về việc giải phóng mọi thứ.

Tuy nhiên, trong lập trình nhúng, khu vực im lặng, có rất nhiều ứng dụng mà bạn hoàn toàn không thể sử dụng phân bổ heap, do bộ nhớ và các ràng buộc thời gian thực cứng; số lượng đối tượng của từng loại sẽ được xử lý là một phần của đặc tả và mọi thứ được phân bổ tĩnh.

Lập trình trò chơi (ít nhất là với những trò chơi có tham vọng đẩy phần cứng) đôi khi rơi vào giữa: bạn có thể sử dụng phân bổ động, nhưng có đủ bộ nhớ và các ràng buộc thời gian thực mềm mà bạn không thể coi bộ cấp phát là hộp đen , hãy để một mình sử dụng bộ sưu tập rác, vì vậy bạn phải sử dụng phân bổ tùy chỉnh. Đây là một trong những lý do C ++ vẫn được sử dụng rộng rãi trong ngành công nghiệp game; nó cho phép bạn làm những việc như http://www.open-std.org/jtc1/sc22/wg21/docs/ con 2007 / n2271.html

Những miền khác nằm trong lãnh thổ ở giữa đó? Trường hợp, ngoài các trò chơi, phân bổ tùy chỉnh được sử dụng nhiều?


1
Một số HĐH sử dụng bộ cấp phát phiến cung cấp bộ đệm ẩn đối tượng nhưng cũng có thể được sử dụng để giảm các lỗi xung đột bộ đệm của bộ xử lý bằng cách ánh xạ các thành viên của đối tượng sang các bộ khác nhau cho bộ đệm được lập chỉ mục modulo 2 ** N (cả hai đều có nhiều bộ nhớ liền kề và bằng cách thay đổi đệm trong tấm). Hành vi bộ nhớ cache có thể quan trọng hơn phân bổ / tốc độ miễn phí hoặc sử dụng bộ nhớ trong một số trường hợp.
Paul A. Clayton

Câu trả lời:


4

Bất cứ khi nào bạn có một ứng dụng có đường dẫn quan trọng về hiệu năng, bạn nên quan tâm đến cách bạn đối xử với bộ nhớ. Hầu hết các ứng dụng phía máy khách của người dùng cuối không thuộc loại này vì chúng là các sự kiện chính và hầu hết các sự kiện đến từ các tương tác với người dùng và điều đó không có nhiều ràng buộc về hiệu năng (nếu có).

Tuy nhiên, rất nhiều phần mềm back-end nên tập trung vào cách xử lý bộ nhớ vì rất nhiều phần mềm đó có thể mở rộng để xử lý số lượng khách hàng cao hơn, số lượng giao dịch lớn hơn, nhiều nguồn dữ liệu hơn .... Khi bạn bắt đầu đẩy các giới hạn, bạn có thể bắt đầu phân tích cách bộ nhớ người dùng phần mềm của bạn và viết các sơ đồ phân bổ tùy chỉnh phù hợp với phần mềm của bạn thay vì dựa vào bộ cấp phát bộ nhớ hoàn toàn chung được viết để xử lý mọi trường hợp sử dụng có thể tưởng tượng được.

Để cho bạn một vài ví dụ ... trong công ty đầu tiên của tôi, tôi đã làm việc với gói Lịch sử, phần mềm chịu trách nhiệm thu thập / lưu trữ / lưu trữ dữ liệu kiểm soát quá trình (nghĩ về một nhà máy, nhà máy điện hạt nhân hoặc nhà máy lọc dầu với 10 triệu cảm biến, chúng tôi sẽ lưu trữ dữ liệu đó). Bất cứ khi nào chúng tôi phân tích bất kỳ tắc nghẽn hiệu suất nào đã ngăn Nhà sử học xử lý nhiều dữ liệu hơn, phần lớn thời gian là vấn đề nằm ở cách xử lý bộ nhớ. Chúng tôi đã trải qua thời gian dài để đảm bảo malloc / miễn phí không được gọi trừ khi chúng thực sự cần thiết.

Trong công việc hiện tại của tôi, tôi làm việc trên gói ghi âm và phân tích kỹ thuật số video giám sát. Với tốc độ 30 khung hình / giây, mỗi kênh nhận được một khung hình video cứ sau 33 mili giây. Trên phần cứng chúng tôi bán, chúng tôi có thể dễ dàng ghi lại 100 kênh video. Vì vậy, đó là một trường hợp khác để đảm bảo rằng trong đường dẫn quan trọng (cuộc gọi mạng => thành phần chụp => phần mềm quản lý đầu ghi => thành phần lưu trữ => đĩa) không có phân bổ bộ nhớ động. Chúng tôi có một bộ cấp phát khung tùy chỉnh, chứa các bộ đệm có kích thước cố định và sử dụng LIFO để sử dụng lại các bộ đệm được phân bổ trước đó. Nếu bạn cần 600Kb dung lượng lưu trữ, bạn có thể kết thúc với bộ đệm 1024Kb, gây lãng phí dung lượng, nhưng vì nó được thiết kế riêng cho mục đích sử dụng của chúng tôi khi mỗi phân bổ rất ngắn, nên nó hoạt động rất tốt vì bộ đệm được sử dụng,

Trong loại ứng dụng tôi đã mô tả (di chuyển nhiều dữ liệu từ A sang B và xử lý số lượng lớn yêu cầu của khách hàng) đi đến đống và trở lại là một nguồn chính của các tắc nghẽn hiệu suất CPU. Giữ phân mảnh heap ở mức tối thiểu là lợi ích thứ cấp, tuy nhiên theo như tôi có thể nói với hầu hết các hệ điều hành hiện đại đã thực hiện các đống phân mảnh thấp (tối thiểu tôi biết Windows cũng vậy, và tôi cũng hy vọng những người khác cũng làm như vậy). Cá nhân, trong hơn 12 năm làm việc trong các loại môi trường này, tôi đã thấy các vấn đề sử dụng CPU liên quan đến heap khá thường xuyên, trong khi chưa bao giờ tôi thấy một hệ thống thực sự bị đống phân mảnh.


"Chúng tôi đã trải qua thời gian dài để đảm bảo malloc / miễn phí không được gọi trừ khi chúng thực sự cần thiết ..." - Tôi biết một số kẻ phần cứng xây dựng bộ định tuyến. Họ thậm chí không bận tâm đến malloc/free. Họ dự trữ một khối bộ nhớ và sử dụng nó như một cấu trúc dữ liệu con trỏ. Hầu hết các công việc của họ giảm để theo dõi các chỉ số.

4

Xử lý video, VFX, hệ điều hành, vv Thông thường mọi người sử dụng chúng quá mức. Cấu trúc dữ liệu và phân bổ không cần phải được tách rời để đạt được phân bổ hiệu quả.

Ví dụ, nó giới thiệu rất nhiều sự phức tạp bổ sung để phân chia phân bổ nút cây hiệu quả trong một quãng tám từ chính octree và dựa vào một bộ cấp phát bên ngoài. Không nhất thiết là vi phạm SRP để kết hợp hai mối quan tâm này lại với nhau và khiến trách nhiệm của octree phải phân bổ nhiều nút cùng một lúc, vì làm như vậy không làm tăng số lượng lý do để thay đổi. Nó có thể, thực tế nói, làm giảm nó.

Ví dụ, trong C ++, một trong những tác dụng phụ bị trì hoãn của việc có các thùng chứa tiêu chuẩn dựa vào bộ cấp phát bên ngoài đã tạo ra các cấu trúc được liên kết như std::mapstd::listđược cộng đồng C ++ coi là gần như vô dụng, vì chúng đang so sánh chúng vớistd::allocatortrong khi các cấu trúc dữ liệu này phân bổ một nút tại một thời điểm. Tất nhiên các cấu trúc được liên kết của bạn sẽ hoạt động kém trong trường hợp đó, nhưng mọi thứ sẽ trở nên khác đi rất nhiều nếu việc phân bổ hiệu quả các nút cho các cấu trúc được liên kết được coi là trách nhiệm của cấu trúc dữ liệu thay vì của cấp phát. Họ vẫn có thể sử dụng phân bổ tùy chỉnh cho các lý do khác như theo dõi / định hình bộ nhớ, nhưng dựa vào bộ cấp phát để làm cho các cấu trúc được liên kết hiệu quả trong khi cố gắng phân bổ các nút một lần, làm cho tất cả chúng, theo mặc định, cực kỳ không hiệu quả, Sẽ ổn thôi nếu nó đi kèm với một cảnh báo nổi tiếng mà các cấu trúc được liên kết bây giờ cần một bộ cấp phát tùy chỉnh, như danh sách miễn phí, để có hiệu quả hợp lý và tránh kích hoạt bộ nhớ cache bỏ qua trái và phải. Thực tế hơn có thể áp dụng có thể là một cái gì đó nhưstd::list<T, BlockSize, Alloc>, trong đó BlockSizechỉ ra số lượng các nút liền kề để phân bổ cùng một lúc cho danh sách miễn phí (chỉ định 1 sẽ có hiệu quả dẫn đến std::listnhư hiện tại).

Nhưng không có sự cảnh báo nào như vậy, điều này dẫn đến cả một cộng đồng những kẻ chặn đầu lặp lại một câu thần chú sùng bái mà các danh sách liên kết là vô dụng, ví dụ


3

Một lĩnh vực khác mà bạn có thể muốn một bộ cấp phát tùy chỉnh là ngăn phân mảnh heap . Theo thời gian, đống của bạn có thể phân bổ các đối tượng nhỏ bị phân mảnh trong suốt đống. Nếu chương trình của bạn không thể giữ bộ nhớ heap cùng nhau, khi chương trình của bạn phân bổ một đối tượng lớn hơn, nó phải yêu cầu thêm bộ nhớ từ hệ thống vì nó không thể tìm thấy một khối miễn phí ở giữa đống phân mảnh hiện có của bạn (quá nhiều các đối tượng đang cản đường). Tổng mức sử dụng bộ nhớ của chương trình của bạn sẽ tăng theo thời gian và bạn sẽ tiêu thụ thêm các trang bộ nhớ không cần thiết. Vì vậy, đây là một vấn đề khá lớn đối với các chương trình dự kiến ​​sẽ chạy trong thời gian dài (nghĩ rằng cơ sở dữ liệu, máy chủ, v.v.).

Trường hợp, ngoài các trò chơi, phân bổ tùy chỉnh được sử dụng nhiều?

Facebook

Kiểm tra jemalloc rằng Facebook đang bắt đầu sử dụng để cải thiện hiệu suất heap của họ và giảm sự phân mảnh.


Đúng. Tuy nhiên, một trình thu gom rác sao chép giải quyết gọn gàng vấn đề phân mảnh, phải không?
rwallace
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.