Чи є альтернативи для складання + heap + статичної моделі пам'яті?


9

Усі програми, які я бачив, організовують свою пам'ять даних в один або кілька стеків викликів (як правило, фіксованого розміру, але іноді немає), кучу та статичну пам'ять. Останнім часом до цього також додано локальне статичне зберігання.

Чи були спроби організувати компонування пам'яті даних кардинально іншим способом, наприклад, без стека викликів? Або організувати пам'ять по-іншому, що здійснює те саме?


Залежить від того, що ви маєте на увазі під "стеком". Ви можете помістити рамки стека викликів у купу (зв’язати їх із покажчиками). Тоді у вас немає виділеної лінійної області пам'яті для стека, але концептуально у вас все ще є стек викликів.

і залежить від того, що ви маєте на увазі під "нещодавно". Я думаю, що локальне зберігання потоків так само, як і потоки. Але раніше це було доступне через системні дзвінки, тоді як тепер новіші мови надають вам доступ до нього безпосередньо.
DXM

Стек викликів необхідний, оскільки процедурні функції повинні знати, хто їх викликав, щоб вони могли повернути результати та продовжити виконання. Діючий механізм, якщо це зробити насправді досить дешево з точки зору циклів процесора, а принаймні з x64, майже всі функціональні аргументи передаються через регістри
Джеймс

2
Ви можете знайти повідомлення Еріка Ліпперта " Чому мати стек?" представляє інтерес. Його головна суть полягає в тому, що стек забезпечує ефективний, простий спосіб відстеження місць пам'яті. Він обговорює одну альтернативу в декількох значно старших дописах, « Стиль продовження передачі» .
Брайан

Відповіді:


8

Можливо, ви захочете відступити назад і побачити, звідки і чому беруться ці існуючі моделі. Коли процес створюється, йому просто надається плоска область зберігання, яка просто індексується від 0 до N. Оскільки ця область зберігання (тут йдеться про оперативну пам’ять) підтримується спеціальним обладнанням та деякими химерними напівпровідниками, це відбувається досить швидко, але це не єдиний у своєму роді. Інші пристрої, такі як жорсткі диски, це по суті те саме, плоский простір, який можна адресувати індексом, але на багато порядків повільніше.

Причина існування "купи" полягає в тому, що для кожної програми було б недоцільно намагатися керувати використанням оперативної пам'яті самостійно. Зрештою, саме так сталося, програмісти достроково планували, для чого використовуватиметься кожне місце оперативної пам'яті. Оскільки програмне забезпечення стало складнішим, хтось сказав, чи не було б добре, якби я міг просто зайти до якоїсь чорної скриньки і сказати "мені потрібно 10 байтів, щоб придумати", і не потрібно турбуватися про всі складні деталі, де і як ці 10 байт походять від того, як їх відновлюють. Ось, що це купа, насправді не стає більш простим, ніж це.

Кожен раз, коли створюється потік, є деякі структури даних (і стек), які отримуються за допомогою тієї самої операції gimme, яку я тільки що описав. Стек майже універсально використовується, тому що він ідеально підходить до кадрів стека функціональних викликів та їх природи LIFO. Теоретично кожне виклик функції та локальні змінні можуть бути розподілені на купі, але це було б занадто дорого, порівняно з лише кількома інструкціями зі збирання, необхідними для оновлення реєстру покажчика стека (ESP на x86).

Місцевий накопичувач ниток (TLS) також побудований поверх купи. Коли нитка створюється в рамках поїздки до купи, щоб виділити пам'ять для структур управління, окремий простір для TLS також виділяється з купи.

Отже, зрештою, все, що у вас є насправді, - це загальний розподільник пам'яті (тобто купа), а все інше - це спеціалізована форма. Іншими словами, якщо ви готові відмовитись від якогось аспекту "я хочу виділити стільки (або як мало), скільки я хочу, зберігайте його стільки, скільки я хочу, і безкоштовно, коли я хочу", ви можете піти з торгівлі вимкнути загальний розподільник купи для іншої моделі, яка пропонує швидкість, але ціною якогось іншого обмеження.

Візьміть стек. Це надзвичайно швидко в порівнянні з купою, але два компроміси - 1) ви не контролюєте, коли звільняється пам'ять; замість того, як тільки функція завершується, все, що ви виділили, вже немає і 2), оскільки стеки, як правило, обмежені за розміром, вам слід обережно розподіляти велику кількість даних безпосередньо у стеку.

Інший тип «моделі пам’яті» - це менеджер віртуальної пам’яті (VMM), який пропонується майже всіма основними ОС через системні дзвінки. VMM дуже схожий на купу в тому сенсі, що ви можете попросити будь-яку кількість пам'яті і зберегти її скільки завгодно. Однак обмеження полягає в тому, що ви можете виділяти пам'ять лише у кратних розмірах сторінки (наприклад, 4 КБ), тому використання VMM безпосередньо спричинить великі накладні витрати в типовому додатку, який часто виділяє 8-24 байти одночасно. Насправді, майже кожна реалізація купи будується на основі VMM спеціально для того, щоб забезпечити дуже загальний, неспеціалізований розподіл з невеликим блоком. Купа переходить до VMM кожного разу, коли їй потрібно більше пам’яті, а потім виділяє в програму багато невеликих шматочків цієї пам’яті.

Якщо у вас є додаток, який потребує розподілу великих блоків, ви можете розглянути можливість прямого переходу до VMM, хоча деякі купи мають вираз if всередині malloc (), і якщо розмір блоку перевищує деякий поріг, вони просто переходять до VMM для вас.

Іншою формою алокаторів замість того, щоб безпосередньо використовувати купу, будуть пули. Пул - це спеціалізований розподільник, де всі блоки однакового розміру. Басейни (так само, як стек і TLS) будуються поверх купи або VMM. Басейни корисні в місцях, де ви виділяєте багато (мільйони) короткочасних, невеликих об’єктів однакового розміру. Подумайте про послугу мережі, що обробляє вхідні запити. Кожен клієнтський запит може призвести до того, що для обробки запиту буде виділена одна і та ж байтна структура. Компроміс із використанням пулів полягає в тому, що кожен пул обробляє лише один розмір блоку (але ви можете створити кілька пулів). Перевага пулів полягає в тому, що оскільки всі об'єкти однакового розміру, йому не потрібна складна логіка. Натомість, коли вам потрібен новий блок, він просто дає вам той, який нещодавно був звільнений.

І, нарешті, пам’ятайте ту річ на жорсткому диску, про яку я згадував. У вас може бути модель пам'яті, яка поводиться як файлова система і дублює ту саму ідею записів каталогів і i-вузлів, щоб дозволити вам ієрархічно розподіляти блоки даних, де кожен блок даних відповідає адресі шляху. Саме це робить tmpfs .

Окрім речей, про які я згадував, я впевнений, що є інші більш спеціалізовані моделі, але врешті-решт, оскільки все базується на просторі адресного простору (тобто, поки деякі генуї не придумають якийсь дивний - не плоский простір $$ ), все повертається до того загального розподільника "gimme", який є або VMM, або купу.


1

Єдині випадки, які я можу придумати, - це спеціалізоване обладнання, де у вас може бути все, що працює у фіксованих місцях у пам'яті. Практично все, що потрібно в поточній моделі пам'яті, потрібно, якщо ви хочете повністю гнучких програм.

Без стека ви не можете мати локальні змінні, стеки викликів тощо. Все, що ви пишете для реалізації, що в кінцевому підсумку буде схоже на стек.

Статична пам’ять і купа, яку ви потенційно можете скинути для певних програм, але знову ж таки вам знадобиться повернути їх у тій чи іншій формі, щоб зробити щось більш вдосконалене.

Тож все, що винайдете для заміни одного з цих трьох, в кінцевому підсумку виглядатиме дуже схожим на один із цих трьох у підсумку ...

Щоб підійти до нього з іншого кута, що ви можете додати, що є новим? Ви потенційно можете сперечатися з такими речами, як графічні / фізичні процесори / кешові процесори / тощо - це нове місце пам’яті, але насправді вони є лише окремим екземпляром або способом прискорити доступ до існуючих моделей.

... так що поки хтось не придумає якийсь гігантський концептуальний стрибок, я думаю, що ми навряд чи давно побачимо якісь серйозні зміни в цій галузі ...


4
Більшість людей схиляються до думки, що поточний спосіб є найкращим / єдиним способом, і якби він дав порожній аркуш, він просто скопіював би те, що вже існує. В інших людей є ті , хто на самому ділі просувають технічний прогрес. Не кажучи про те, що я особисто знаю про будь-які серйозні конкуруючі моделі (якщо не рахувати квантові комп'ютери), але стверджувати, що все, що можна було б придумати, виглядатиме так само, як і те, що вже є, по суті є формою кругових міркувань.
Aaronaught

@Aaronaught: зворотний бік вашого аргументу полягає в тому, що інші люди витрачають багато часу, грошей і енергії на роздуми поза коробкою і на кожні 1000 (можливо, набагато більше) з них, з часом можна просунути технологічний прогрес, а решта дістатися нікуди . Тоді як перша група, яку можна вважати більш практичною, вважає ці існуючі моделі такими, що є, та впроваджує інновації на їх основі :)
DXM

@aaronaught Я думаю, що я покрив це "так, поки хтось не придумає якийсь гігантський концептуальний стрибок";) Якщо у вас є краща альтернативна модель, сміливо пропонуйте це ... якщо не почуватись трохи лицемірно скаржитися на "деякі люди", коли ви один з них :)
Тим Б

1
@DXM: Отже? Я казав, що ми всі повинні вкладати свій час у дослідження нових моделей пам'яті? Я лише вказував на (суттєву) ваду твердження, що людина може вигадувати лише речі, які вже були винайдені.
Aaronaught

Претензія, яку я ніколи не висував ...
Тім Б
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.