Навіщо збирання сміття, якщо там є розумні покажчики


67

У наші дні стільки мов збирають сміття. Він навіть доступний для C ++ третіми сторонами. Але C ++ має RAII та розумні покажчики. Тож який сенс використовувати сміття? Це робить щось зайве?

І в інших мовах, таких як C #, якщо всі посилання розглядаються як розумні покажчики (не відхиляючи RAII в стороні), за специфікацією та реалізацією, чи все-таки будуть потрібні смітники? Якщо ні, то чому це не так?


1
Одне, що я зрозумів, задавши це запитання - Розумним покажчикам потрібен RAII для управління автоматичною угодою .
Гульшань

8
Розумні покажчики означають використання RAII для GC;)
Даріо

Heh, c # повинна мати можливість для обробки всіх "сміття" з RAII. Циркулярні посилання можна виявити при відключенні програми. Все, що нам потрібно, - це побачити, які розподіли залишаються в пам'яті після розміщення Program.cs-класу. Тоді кругові посилання можна замінити якимись посиланнями на тиждень.
AareP

4
Відповідь
Гульшан

Відповіді:


67

Отже, який сенс використовувати сміття?

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

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

  • Пропускна здатність . Інтелектуальні покажчики є однією з найменш ефективних форм збору сміття, особливо в контексті багатопотокових програм, коли довідкові показники накопичуються атомно. Існують вдосконалені методи підрахунку довідок, покликані полегшити це, але трасування ГК все ще є алгоритмом вибору у виробничих середовищах.

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


23
Не можу повірити, що ця відповідь виявилася найкращою. Це показує повне нерозуміння розумних покажчиків C ++ і робить претензії, які настільки сильно синхронізовані з реальністю, що її просто смішно. По-перше, розумний вказівник, який у добре розробленому фрагменті коду С ++ буде найбільш домінуючим, - це унікальний покажчик, а не покажчик розділення. en.cppreference.com/w/cpp/memory/unique_ptr І по-друге, я не можу повірити, що ви насправді заявляєте про переваги "продуктивності" та переваги в режимі реального часу недетермінованого збору сміття над розумними покажчиками.
user1703394

4
@ user1703394 Здається, що відповідач мав на увазі загальні покажчики (правильно чи неправильно, я не зовсім впевнений, що пропонують ОП), які менш ефективні, ніж недетермінований збір сміття.
Натан Купер

8
Це все аргументи "солом'яної людини" і справедливі лише в тому випадку, якщо ви повністю ігноруєте фактичний питання або ігноруєте фактичні схеми використання різних типів розумних покажчиків. Питання стосувалося розумних покажчиків. Так shared_ptr - це розумний покажчик, і так shared_ptr - найдорожчий з розумних покажчиків, але ні, немає фактичного аргументу для їх повного використання десь близько, щоб зробити будь-який аргумент ефективності близьким до релевантного. Серйозно, цю відповідь слід перенести на питання про підрахунок посилань. Я поганий підрахунок відповіді на хороший запит розумного вказівника.
user1703394

4
"Інтелектуальні покажчики - не ширша концепція", серйозно? Ви не знаєте, наскільки ця заява підриває всі можливі вагомі аргументи, які ви зробили до цього часу. Можливо, подивіться на власність і переміщення семантики Rust: koerbitz.me/posts/… Людям, які мають історичний досвід C ++, легко пропустити той факт, що C ++ 11 / C ++ 14 зі своєю моделлю пам'яті, покращеною розумною покажчики і семантика переміщення - це зовсім інший звір, ніж їх попередники. Погляньте, як це робить Іржа, вона чистіша за С ++ та надає свіжу перспективу.
user1703394

6
@ user1703394: "Неограниченные паузи через деструктори - прикрою властивістю RAII, що використовується для ресурсів не пам'яті". Ні, це не має нічого спільного з ресурсами, що не належать до пам'яті.
Джон Харроп

63

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

На це питання є пару відповідей. Найголовніше перше:

  1. Ви гарантуєте, що весь код може використовувати його для взаємодії. Думаю, це велика причина, чому повторне використання коду та обмін кодом насправді не знімалися доти, доки Java / C # / Python / Ruby. Бібліотекам потрібно спілкуватися, і єдиною надійною загальною мовою, якою вони володіють, є те, що є у самій мовній специфікації (і, до певної міри, її стандартна бібліотека). Якщо ви коли-небудь намагалися повторно використовувати бібліотеки на C ++, ви, швидше за все, відчули жахливий біль, який не викликає стандартна семантика пам'яті. Я хочу передати структуру якомусь lib. Чи повинен я пройти довідку? Покажчик? scoped_ptr?smart_ptr? Я передаю право власності, чи ні? Чи є спосіб це вказати? Що робити, якщо ліб потрібно виділити? Чи повинен я дати йому розподільник? Не роблячи управління пам’яттю частиною мови, C ++ змушує кожну пару бібліотек домогтися узгодження власної стратегії тут, і дійсно важко змусити їх погодитися. GC робить це повною проблемою.

  2. Ви можете спроектувати синтаксис навколо нього. Оскільки C ++ не інкапсулює управління самою пам'яттю, він повинен забезпечити ряд синтаксичних гачків, щоб дозволити коду рівня користувача виражати всі деталі. У вас є вказівники, посилання, constоператори перенаправлення, оператори непрямості, адреса і т.д. Усі ці оператори зникають, а мова стає чистішою та простішою.

  3. Ви отримуєте високу віддачу від інвестицій. Значення, яке створює будь-який фрагмент коду, множиться на кількість людей, які його використовують. Це означає, що чим більше у вас користувачів, тим більше ви можете дозволити собі витратити на частину програмного забезпечення. Коли ви переміщуєте функцію на мову, всі користувачі мови будуть використовувати її. Це означає, що ви можете виділити на це більше зусиль, ніж ви могли б на бібліотеку, яку використовує лише підмножина цих користувачів. Ось чому такі мови, як Java та C #, мають абсолютно першокласні віртуальні машини та фантастично якісні збирачі сміття: вартість їх розробки амортизується у мільйонів користувачів.


Фантастична відповідь! Якби тільки я міг подати заявку не раз ...
Дін Гардінг,

10
Варто зазначити, що збирання сміття реально не реалізовано на самій мові C #, а в .NET Framework , зокрема в загальній мові виконання (CLR).
Роберт Харві

6
@RobertHarvey: Він не реалізований мовою, але без співпраці мови він би не працював . Наприклад, компілятор повинен містити інформацію, що вказує в кожній точці коду розташування кожного регістра або зміщення кадру стека, що містить посилання на незакріплений об'єкт. Це абсолютний відсутність винятків - будь-який інваріант , який не можна було б підтримати без підтримки мови.
supercat

Головною перевагою того, що GC підтримує мову та необхідний фреймворк, полягає в тому, що вона гарантує, що ніколи не буде посилань на пам'ять, яка може бути виділена для якоїсь іншої мети. Якщо хтось закликає Disposeоб'єкт, який інкапсулює растрову карту, будь-яке посилання на цей об’єкт буде посиланням на розміщений растровий об'єкт. Якщо об'єкт було видалено передчасно, тоді як інший код все ще очікує його використання, клас растрових зображень може гарантувати, що інший код вийде з ладу передбачувано . Навпаки, використання посилання на звільнену пам'ять - це Невизначена поведінка.
supercat

34

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

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

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

Тепер, як ви вже заявляли, розумні покажчики можна використовувати для впровадження форми збору сміття.

Але потяг думки йде наступним шляхом:

  1. Збір сміття - це класна річ, як це зручно, і я повинен подбати про меншу кількість речей
  2. Тому: я хочу збирання сміття моєю мовою
  3. Тепер, як можна отримати GC моєю мовою?

Звичайно, ви можете спроектувати його так із самого початку. C # був розроблений так, щоб збирати сміття, тому просто newваш об’єкт і він буде випущений, коли посилання випадуть із сфери застосування. Як це зробити, залежить від компілятора.

Але в С ++ не було призначено збирання сміття. Якщо ми виділимо якийсь вказівник, int* p = new int;і він не виходить за межі, pвін видаляється зі стека, але ніхто не піклується про виділену пам'ять.

Тепер єдине, що ви маєте з самого початку - це детерміновані деструктори . Коли об'єкт залишає сферу, в якій він був створений, викликається його деструктор. У поєднанні з шаблонами та перевантаженням оператора ви можете розробити об’єкт обгортки, який веде себе як вказівник, але використовує функцію деструктора для очищення доданих до нього ресурсів (RAII). Ви називаєте цього розумним вказівником .

Це все специфічно для C ++: перевантаження операторів, шаблони, деструктори ... У цій конкретній мовній ситуації ви розробили розумні покажчики, щоб надати вам потрібний GC.

Але якщо ви розробляєте мову з GC з самого початку, це лише деталь реалізації. Ви просто скажете, що об'єкт буде очищений, і компілятор зробить це за вас.

Розумні покажчики, як у C ++, ймовірно, не можуть бути навіть можливими на таких мовах, як C #, які взагалі не мають детермінованого знищення (C # працює навколо цього, надаючи синтаксичний цукор для виклику .Dispose()на певні об'єкти). Нереференційовані ресурси, нарешті, будуть повернені GC, але не визначено, коли саме це відбудеться.

А це, в свою чергу, може дозволити ГК зробити свою роботу більш ефективно. Будучи вбудованим у мову глибше, ніж розумні покажчики, встановлені на ньому, .NET GC може, наприклад, затримувати операції з пам’яттю та виконувати їх у блоках, щоб здешевити або навіть перемістити пам’ять для підвищення ефективності залежно від частоти об'єктів доступ до них.


C # має форму детермінованого знищення через IDisposableі using. Але це вимагає трохи зусиль програміста, тому його зазвичай використовують лише для дуже дефіцитних ресурсів, таких як ручки підключення до бази даних.
JSB ձոգչ

7
@JSBangs: Саме так. Так само як C ++ будує розумні покажчики навколо RAII, щоб отримати GC, C # піде іншим шляхом і будує "розумних розпорядників" навколо GC, щоб отримати RAII;) Насправді, шкода, що RAII настільки важкий у C #, як це чудово для винятку- безпечна робота з ресурсами. Наприклад, F # приміряє простіший IDisposableсинтаксис, просто замінивши звичайний let ident = valueна use ident = value...
Даріо,

@Dario: "C # йде іншим шляхом і створює" розумні розпорядники "навколо GC, щоб отримати RAII". RAII в C # з usingвзагалі не має нічого спільного зі збиранням сміття, він просто викликає функцію, коли змінна випадає із сфери застосування так само, як деструктори в C ++.
Джон Харроп

1
@Jon Harrop: Будь ласка, що? Заява, яку ви цитуєте, стосується звичайних деструкторів C ++, без будь-яких підрахунків посилань / розумних покажчиків / збору сміття.
Даріо

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

4

На мій погляд, є дві великі відмінності між збиранням сміття та розумними покажчиками, які використовуються для управління пам’яттю:

  1. Розумні покажчики не можуть збирати циклічний сміття; сміттєзбірник
  2. Інтелектуальні покажчики виконують всю роботу в моменти посилання, перенаправлення та дислокації в потоці програми; збирання сміття не потрібно

Перший означає, що GC збиратиме сміття, яке розумні покажчики не будуть; якщо ви використовуєте смарт-покажчики, вам слід уникати створення такого сміття або бути готовим поводитися з ним вручну.

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

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

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


6
@Tom: подивіться відповідь Даріо, щоб отримати детальну інформацію про розумні покажчики. Що стосується переваг розумних покажчиків - детермінований делокація може бути величезною перевагою при використанні для управління ресурсами (не тільки пам'яттю). Насправді це виявилося настільки важливим, що Microsoft представила usingблок у наступних версіях C #. Крім того, недетерміновану поведінку ГК можна заборонити в системах реального часу (саме тому ГК там не використовуються). Крім того, не будемо забувати, що ГК настільки складні, щоб виправитись так, що більшість насправді протікає пам'ять і є досить неефективними (наприклад, Боем…).
Конрад Рудольф

6
Недетермінізм ГК - це, на мій погляд, трохи червона оселедець - є системи GC, які підходять для використання в режимі реального часу (як Recycler IBM), хоча ті, які ви бачите в настільних та серверних віртуальних машинах, не є. Крім того, використання розумних покажчиків означає використання malloc / free, а звичайні реалізації malloc недетерміновані через необхідність пошуку вільного списку. Рухомі системи GC мають більше детермінованих часів розподілу, ніж системи malloc / free, хоча, звичайно, менше детермінованих часів дислокації.
Том Андерсон

3
Щодо складності: так, ГК є складними, але я не усвідомлюю, що "більшість насправді протікає пам'ять і є досить неефективними", і мені було б цікаво побачити деякі докази інакше. Boehm не є доказом, тому що це дуже примітивна реалізація, і вона побудована для обслуговування мови C, де точний GC принципово неможливий через відсутність безпеки типу. Це хоробрі зусилля, і те, що це працює взагалі, дуже вражає, але ви не можете сприйняти це як приклад GC.
Том Андерсон

8
@Jon: рішуче не глупота . bugzilla.novell.com/show_bug.cgi?id=621899 або, загалом ,: flyingfrogblog.blogspot.com/2009/01/… Це добре відоме та властивість усіх консервативних ГК.
Конрад Рудольф

3
"Вартість виконання сучасної GC менша, ніж звичайна система malloc / free." Червона оселедець тут. Це лише тому, що традиційний малалок - жахливо неефективний алгоритм. Сучасні алокатори, які використовують декілька відра для різних розмірів блоків, набагато швидше виділяють, набагато менше схильні до роздроблення купи, і все ж дають вам швидке розселення.
Мейсон Уілер

3

Термін збирання сміття означає, що сміття потрібно збирати. У C ++ розумні покажчики надходять у декількох смаках, головне - унікальний_ptr. Унікальний_ptr - це в основному одна конструкція власності та масштабування. У добре розробленому фрагменті коду більшість матеріалів, що виділяються в купі, зазвичай розташовуються за розумними покажчиками унікальних_ptr і право власності на ці ресурси буде чітко визначено у всі часи. Навряд чи є накладні витрати на унікальний_ptr, а jedinstveний_птр забирає більшість проблем з керуванням пам’яттю вручну, які традиційно залучають людей до керованих мов. Тепер, коли більше ядер, що працюють одночасно, стають все більш загальним благом, принципи дизайну, які керують кодом для використання унікальної та чітко визначеної власності в будь-який момент часу, стають більш важливими для продуктивності.

Навіть у добре розробленій програмі, особливо в багатопотокових середовищах, не все можна виразити без спільних структур даних, а для тих структур даних, які справді потребують, потокам потрібно спілкуватися. RAII в c ++ працює досить добре для проблем, пов'язаних із життям в одній потоковій установці, в умовах багатопотокової установки час життя об'єктів може бути не повністю ієрархічно визначений стеком. У цих ситуаціях використання shared_ptr пропонує велику частину рішення. Ви створюєте спільну власність на ресурс, і це в C ++ - це єдине місце, де ми бачимо сміття, але в таких невеликих кількостях, що належним чином розроблена програма c ++ повинна розглядатися більше для впровадження "сміття" з колекцією спільного ptr, ніж повноцінного збору сміття реалізовано іншими мовами. У C ++ просто не так багато "сміття"

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

Отже, підсумовуючи все, якщо під загальним використанням покажчика ви маєте на увазі широке використання jedinstveного_птр у поєднанні з акторською моделлю обчислювального підходу для багатопотокового програмування та обмежене використання shared_ptr, ніж інші форми збору сміття не купують вас додаткові переваги. Якщо все-таки підхід із загальним доступом все-таки змусить вас узагальнити shared_ptr, то вам слід подумати про перемикання моделей одночасності або перехід на керовану мову, більш орієнтовану на ширший спільний доступ до власності та одночасний доступ до структур даних.


1
Це означає, Rustщо не потрібно збирання сміття?
Гульшан

1
@Gulshan Rust - одна з небагатьох мов, яка підтримує безпечні унікальні покажчики.
CodesInChaos

2

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

Проблема є, якщо у вас кругові посилання. Тобто, A має посилання на B, B має посилання на C, а C має посилання на A. Якщо ви використовуєте розумні покажчики, то для звільнення пам'яті, асоційованої з A, B і C, вам потрібно вручну введіть туди "перерву" кругової посилання (наприклад, використовуючи weak_ptrC ++).

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

Таким чином, кругові посилання вже не мають значення - доки ані A, B і C не доступні , пам'ять може бути відтворена.

Є й інші переваги «справжнього» вивезення сміття. Наприклад, розподіл пам’яті надзвичайно дешево: просто збільште вказівник на «кінець» блоку пам'яті. Передача має постійні амортизовані витрати. Але звичайно такі мови, як C ++, дозволяють реалізовувати управління пам’яттю практично будь-яким способом, який вам подобається, так що ви можете придумати стратегію розподілу, яка ще швидша.

Звичайно, в C ++ кількість пам'яті, виділеної купу, як правило, менше, ніж мова, що перебуває на еталонах, як C # /. NET. Але це насправді не проблема збору сміття та розумних покажчиків.

У будь-якому випадку, проблема не в різанні та сухій кращій, ніж інша. У кожного з них є переваги та недоліки.


2

Йдеться про продуктивність . Нерозподільна пам'ять вимагає великого адміністрування. Якщо розмежування працює у фоновому режимі, продуктивність переднього плану збільшується. На жаль, розподіл пам’яті не може бути лінивим (виділені об’єкти будуть використані у святий наступний момент), але вивільнити об’єкти можна.

Спробуйте в C ++ (без будь-якої GC) виділити велику купу об'єктів, надрукувати "привіт", а потім видалити їх. Ви здивуєтеся, скільки часу потрібно, щоб звільнити об’єкти.

Також GNU libc забезпечує більш ефективні інструменти для нерозподілення пам'яті, див. Перешкоди . Потрібно зауважити, я не маю досвіду з перешкодами, я ніколи їх не використовував.


У принципі у вас є точка, але слід зазначити, що це питання, яке має дуже просте рішення: використовуйте аллокатор пулу або невеликий розподільник об'єктів для згрупування угод. Але це, правда, вимагає (трохи) більше зусиль, ніж те, що GC працює у фоновому режимі.
Конрад Рудольф

Так, звичайно, GC набагато комфортніше. (Особливо для початківців: проблем із власністю немає, навіть оператора видалення немає.)
ern0

3
@ ern0: ні. Вся суть інтелектуальних покажчиків (підрахунку посилань) полягає в тому, що немає жодної проблеми власності та оператора видалення.
Конрад Рудольф

3
@Jon: що, чесно кажучи, більшість часу. Якщо ви добровільно ділите стан об'єкта між різними потоками, у вас виникнуть зовсім інші проблеми. Я визнаю, що багато хто програмує саме так, але це наслідок поганих абстракцій, що існували до недавнього часу, і це не дуже хороший спосіб зробити багатопотокове читання.
Конрад Рудольф

1
Розміщення часто не робиться "у фоновому режимі", а швидше призупиняє всі нитки переднього плану. Збір сміття в режимі пакетної роботи, як правило, виграш від продуктивності, незважаючи на паузацію ниток переднього плану, оскільки він дозволяє консолідувати невикористаний простір. Можна розділити процеси збору сміття та ущільнення купи, але - особливо в рамках, що використовують прямі посилання, а не ручки - вони обидва, як правило, є процесами "зупинки світу", і це найчастіше практично робити разом.
supercat

2

Збір сміття може бути більш ефективним - він, в основному, «накопичує» накладні витрати управління пам’яттю і робить це все відразу. Взагалі це призведе до того, що менше загального процесора буде витрачено на дерозподіл пам'яті, але це означає, що у вас буде великий сплеск активності дерозподілення в якийсь момент. Якщо GC не розроблений належним чином, це може стати видимим для користувача як "пауза", тоді як GC намагається виділити пам'ять. Більшість сучасних ГК дуже добре зберігають це невидиме для користувача, за винятком самих несприятливих умов.

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

Якщо ви робите щось там, де важлива чуйність, я б запропонував, щоб розумні покажчики / підрахунок посилань точно повідомляли про те, що відбувається, тому ви можете знати, кодуючи те, що може стати видимим вашим користувачам. У налаштуваннях GC ви маєте лише найбільш ефемерний контроль над сміттєзбірником, і вам просто доведеться спробувати обійти справу.

З іншого боку, якщо загальна пропускна здатність є вашою метою, система на основі GC може бути набагато кращим вибором, оскільки вона мінімізує ресурси, необхідні для управління пам’яттю.

Цикли: Я не вважаю проблему циклів істотною. У системі, де у вас є розумні покажчики, ви схиляєтесь до структур даних, які не мають циклів, або ви просто обережні, як ви відпускаєте такі речі. При необхідності об’єкти зберігача, які вміють ламати цикли у власних об'єктах, можуть використовуватися для автоматичного забезпечення належного знищення. У деяких сферах програмування це може бути важливим, але для більшості щоденних робіт це не має значення.


1
"в якийсь момент у вас буде великий сплеск активності з розподілу". Бігова доріжка Бейкера - приклад прекрасно поступового збору сміття. memorymanagement.org/glossary/t.html#treadmill
Джон Харроп

1

Обмеження номер один для інтелектуальних покажчиків - це те, що вони не завжди допомагають проти кругових посилань. Наприклад, у вас є об'єкт Зберігання інтелектуального вказівника на об’єкт B і об'єкт B зберігає інтелектуальний вказівник на об’єкт A. Якщо вони залишаються разом, не скидаючи жодного з покажчиків, вони ніколи не будуть розміщені.

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


1

Це спектр .

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

"Я скажу тобі, що робити, ти це роби. Повір мені".

Збір сміття - це інший кінець спектру. У вас дуже мало контролю, але це подбало про вас:

"Я скажу вам, що я хочу, ви зробите це".

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

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


0

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

Все, що стосується збору сміття, посилань на дані, які можуть бути переміщені, ущільнення купи тощо, виконує роботу в межах обмежень, наведених вище парадигмою "шматок пам'яті з адресним вказівником". Те ж саме і з розумними покажчиками - ви ВИНАГО повинні змусити код працювати на фактичному обладнання.

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