Có các lựa chọn thay thế cho stack + heap + mô hình bộ nhớ tĩnh không?


9

Tất cả các chương trình tôi đã thấy tổ chức bộ nhớ dữ liệu của họ thành một hoặc nhiều ngăn xếp cuộc gọi (thường là kích thước cố định, nhưng đôi khi không), heap và bộ nhớ tĩnh. Gần đây lưu trữ tĩnh chủ đề cục bộ cũng đã được thêm vào này.

Đã có bất kỳ nỗ lực nào để sắp xếp bố cục bộ nhớ dữ liệu theo một cách hoàn toàn khác, ví dụ như không có ngăn xếp cuộc gọi? Hoặc tổ chức bộ nhớ theo một cách khác mà hoàn thành cùng một điều?


Phụ thuộc vào những gì bạn có nghĩa là "ngăn xếp". Bạn có thể đặt các khung ngăn xếp cuộc gọi vào heap (liên kết chúng với các con trỏ). Sau đó, bạn không có vùng nhớ tuyến tính dành riêng cho ngăn xếp, nhưng về mặt khái niệm bạn vẫn có ngăn xếp cuộc gọi.

và phụ thuộc vào những gì bạn có nghĩa là "gần đây". Tôi nghĩ rằng lưu trữ cục bộ chủ đề là cũ như chủ đề. Nhưng trước đây có thể truy cập thông qua các cuộc gọi hệ thống, trong khi bây giờ các ngôn ngữ mới hơn cho phép bạn truy cập trực tiếp vào nó.
DXM

Ngăn xếp cuộc gọi là cần thiết vì các chức năng thủ tục cần biết ai đã gọi chúng để họ có thể trả về kết quả và tiếp tục thực hiện. Cơ chế hiện tại nếu thực hiện điều đó thực sự khá rẻ về chu kỳ CPU và với ít nhất là x64, hầu như tất cả các đối số chức năng đều được chuyển qua các thanh ghi
James

2
Bạn có thể tìm thấy bài viết của Eric Lippert, Tại sao có một ngăn xếp? lãi. Điểm chính của anh ta là một ngăn xếp cung cấp một cách hiệu quả, đơn giản để theo dõi các vị trí bộ nhớ. Ông thảo luận về một sự thay thế trong một số bài viết cũ hơn nhiều, Phong cách tiếp tục .
Brian

Câu trả lời:


8

Bạn có thể muốn lùi lại và xem những mô hình hiện có đến từ đâu và tại sao. Khi một quy trình được tạo, nó chỉ được cung cấp một vùng lưu trữ phẳng được lập chỉ mục đơn giản từ 0 đến N. Bởi vì vùng lưu trữ này (nói về RAM ở đây) được hỗ trợ bởi một phần cứng chuyên dụng và một số chất bán dẫn lạ mắt, nó xảy ra khá nhanh, nhưng nó không phải là người duy nhất thuộc loại này. Các thiết bị khác như ổ cứng về cơ bản là giống nhau, không gian phẳng có thể định địa chỉ bằng một chỉ mục, nhưng nhiều đơn đặt hàng có cường độ chậm hơn.

Lý do tại sao "một đống" tồn tại là bởi vì nó sẽ không thực tế đối với mỗi ứng dụng để cố gắng tự quản lý việc sử dụng RAM. Quay trở lại vào ban ngày, đó chính xác là cách nó đã xảy ra, các lập trình viên đã lên kế hoạch trước thời hạn chính xác từng vị trí RAM sẽ được sử dụng cho mục đích gì. Khi phần mềm trở nên phức tạp hơn, ai đó đã nói, sẽ không hay nếu tôi có thể đi đến một hộp đen nào đó và nói "Tôi cần 10 byte vậy gimme" và không phải lo lắng về tất cả các chi tiết phức tạp về vị trí và 10 byte đó như thế nào đến từ hoặc làm thế nào họ được khai hoang. Đó là một đống, không thực sự trở nên cơ bản hơn thế.

Mỗi khi một luồng được tạo, có một số cấu trúc dữ liệu (và một ngăn xếp), được thu nhận bằng cách sử dụng cùng một "thao tác gimme" mà tôi vừa mô tả. Một ngăn xếp chỉ được sử dụng phổ biến vì nó phù hợp hoàn hảo với các khung ngăn xếp cuộc gọi chức năng và bản chất LIFO của chúng. Về lý thuyết, mỗi lệnh gọi hàm và biến cục bộ có thể được phân bổ trên heap, nhưng điều đó đơn giản là quá đắt, so với chỉ một vài hướng dẫn lắp ráp cần có để cập nhật thanh ghi con trỏ ngăn xếp (ESP trên x86).

Lưu trữ cục bộ luồng (TLS) cũng được xây dựng trên đỉnh heap. Khi một luồng được tạo, như một phần của chuyến đi đến vùng heap để phân bổ bộ nhớ cho các cấu trúc quản lý, một không gian riêng cho TLS cũng được phân bổ từ vùng heap.

Vì vậy, cuối cùng, tất cả những gì bạn thực sự có là một cấp phát bộ nhớ chung (tức là heap) và mọi thứ khác là một hình thức chuyên biệt trên đó. Nói cách khác, nếu bạn sẵn sàng từ bỏ một số khía cạnh của "Tôi muốn phân bổ bao nhiêu (hoặc ít) như tôi muốn, hãy giữ nó miễn là tôi muốn và miễn phí bất cứ khi nào tôi muốn", bạn có thể thoát khỏi giao dịch tắt phân bổ heap chung cho một mô hình khác cung cấp tốc độ nhưng với chi phí của một số hạn chế khác.

Lấy chồng. Nó cực kỳ nhanh khi so sánh với heap, nhưng hai sự đánh đổi là 1) bạn không kiểm soát khi bộ nhớ được giải phóng; thay vào đó một khi chức năng thoát, bất cứ thứ gì bạn phân bổ đều biến mất và 2) vì các ngăn xếp thường bị giới hạn về kích thước, bạn nên cẩn thận phân bổ số lượng lớn dữ liệu trực tiếp trên ngăn xếp.

Một loại "mô hình bộ nhớ" khác là Trình quản lý bộ nhớ ảo (VMM) được cung cấp bởi mọi hệ điều hành chính thông qua các cuộc gọi hệ thống. VMM rất giống với heap theo nghĩa bạn có thể yêu cầu bất kỳ dung lượng bộ nhớ nào và giữ nó miễn là bạn muốn. Tuy nhiên, hạn chế là bạn chỉ có thể phân bổ bộ nhớ theo bội số kích thước trang (ví dụ 4KB) nên việc sử dụng VMM trực tiếp sẽ gây ra nhiều chi phí trong một ứng dụng thông thường thường phân bổ 8-24 byte mỗi lần. Trong thực tế, gần như mọi triển khai heap đều được xây dựng dựa trên VMM đặc biệt cho các mục đích cho phép phân bổ chặn nhỏ rất chung chung, không chuyên biệt, nhỏ . Heap chuyển đến VMM bất cứ khi nào nó cần thêm bộ nhớ và sau đó loại bỏ nhiều phần nhỏ của bộ nhớ đó cho ứng dụng.

Nếu bạn có một ứng dụng, có nhu cầu phân bổ các khối lớn, bạn có thể cân nhắc đến trực tiếp VMM, mặc dù một số heap có câu lệnh if bên trong malloc () và nếu kích thước khối lớn hơn ngưỡng nào đó, chúng chỉ cần chuyển đến VMM cho bạn.

Một hình thức phân bổ khác thay vì trực tiếp sử dụng heap, sẽ là pool. Một hồ bơi là một phân bổ chuyên biệt trong đó tất cả các khối có cùng kích thước. Các hồ bơi (giống như stack và TLS) được xây dựng trên đỉnh heap hoặc VMM. Bể bơi rất hữu ích ở những nơi bạn phân bổ rất nhiều (hàng triệu) vật thể nhỏ, có cùng kích thước. Hãy suy nghĩ một dịch vụ mạng xử lý các yêu cầu đến. Mỗi yêu cầu máy khách có thể dẫn đến cấu trúc byte N giống nhau được phân bổ để xử lý yêu cầu đó. Sự đánh đổi với việc sử dụng các nhóm là mỗi nhóm chỉ xử lý một kích thước khối (nhưng bạn có thể tạo nhiều nhóm). Ưu điểm của pool là bởi vì tất cả các đối tượng có cùng kích thước, nó không yêu cầu logic phức tạp. Thay vào đó, bất cứ khi nào bạn cần một khối mới, nó sẽ cung cấp cho bạn khối mới được giải phóng gần đây.

Và cuối cùng, hãy nhớ rằng điều ổ cứng tôi đã đề cập lên trên. Bạn có thể có một mô hình bộ nhớ hoạt động giống như một hệ thống tệp và sao chép cùng một ý tưởng về các mục nhập thư mục và các nút i để cho phép bạn phân bổ phân cấp các khối dữ liệu trong đó mỗi khối dữ liệu được xử lý theo một đường dẫn. Đó chính xác là những gì tmpfs làm.

Ngoài những thứ tôi đã đề cập, tôi chắc chắn còn có những mô hình chuyên dụng khác, nhưng cuối cùng vì mọi thứ đều dựa trên không gian địa chỉ phẳng (đó là cho đến khi một số genuis xuất hiện một loại kỳ lạ - một không gian không phẳng $$ ), tất cả quay trở lại với cấp phát "gimme" chung đó là VMM hoặc heap.


1

Các trường hợp duy nhất tôi có thể nghĩ là trong phần cứng chuyên dụng nơi bạn có thể có mọi thứ chạy ở các vị trí cố định trong bộ nhớ. Khá nhiều thứ trong mô hình bộ nhớ hiện tại là bắt buộc nếu bạn muốn các chương trình hoàn toàn linh hoạt.

Không có ngăn xếp, bạn không thể có các biến cục bộ, gọi các ngăn xếp, v.v. Bất cứ điều gì khác bạn viết để thực hiện sẽ kết thúc giống như ngăn xếp.

Bộ nhớ tĩnh và heap bạn có thể bỏ qua cho một số ứng dụng nhất định, nhưng một lần nữa bạn sẽ cần chúng trở lại dưới dạng này hoặc dạng khác để làm bất cứ điều gì cao cấp hơn.

Vì vậy, bất cứ điều gì bạn phát minh ra để thay thế một trong ba người này cuối cùng sẽ trông rất giống một trong ba người này cuối cùng ...

Để tiếp cận nó từ góc độ khác, bạn có thể thêm cái gì mới? Bạn có khả năng có thể tranh luận những thứ như bộ xử lý đồ họa / vật lý / bộ nhớ cpu / vv là một vị trí bộ nhớ mới, nhưng thực sự chúng chỉ là một ví dụ riêng biệt hoặc một cách để tăng tốc truy cập vào các mô hình hiện có.

... Vì vậy, cho đến khi ai đó nghĩ ra một bước nhảy vọt về khái niệm khổng lồ, tôi nghĩ rằng chúng ta khó có thể thấy bất kỳ thay đổi lớn nào trong lĩnh vực này trong một thời gian dài ...


4
Hầu hết mọi người có xu hướng cho rằng cách hiện tại là cách tốt nhất / duy nhất và nếu được đưa ra một bản trống sẽ chỉ sao chép những gì đã tồn tại. Những người khác là những người thực sự tiến bộ công nghệ. Không phải nói rằng cá nhân tôi biết về bất kỳ mô hình cạnh tranh nghiêm trọng nào (trừ khi bạn đếm máy tính lượng tử), nhưng tuyên bố rằng bất cứ điều gì người ta có thể nghĩ ra sẽ giống như những gì đã tồn tại về cơ bản là một hình thức lý luận tròn.
Aaronaught

@Aaronaught: mặt trái của lập luận của bạn là người khác dành hàng tấn thời gian, tiền bạc và năng lượng để suy nghĩ bên ngoài và cứ 1000 (có thể nhiều hơn nữa), một người cuối cùng có thể tiến bộ công nghệ, trong khi phần còn lại không đi đến đâu . Trong khi nhóm đầu tiên, người có thể cân nhắc thực tế hơn, sẽ đưa các mô hình hiện có này và đổi mới lên trên chúng :)
DXM

@aaronaught Tôi nghĩ rằng tôi đã đề cập đến điều đó với "vì vậy cho đến khi ai đó nghĩ ra một bước nhảy vọt về mặt khái niệm nào đó";) Nếu bạn có một mô hình thay thế tốt hơn, hãy đề nghị nó ... nếu không cảm thấy hơi đạo đức giả để phàn nàn về "Một số người" khi bạn là một trong số họ :)
Tim B

1
@DXM: Vậy sao? Tôi có nói rằng tất cả chúng ta nên đầu tư thời gian vào việc nghiên cứu các mô hình bộ nhớ mới không? Tôi chỉ chỉ ra lỗ hổng (đáng kể) trong tuyên bố rằng một người chỉ có thể phát minh ra những thứ đã được phát minh ra.
Aaronaught

Một yêu cầu mà tôi chưa bao giờ đưa ra ...
Tim B
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.