Недоліки керованої оперативної пам'яті


38

Мені дуже подобається управління пам’яттю на основі сфери (SBMM) або RAII , як це частіше (заплутано?) Посилається на спільноту C ++. Наскільки я знаю, крім C ++ (і C), немає жодної іншої мови, яка використовується сьогодні, що робить SBMM / RAII їх основним механізмом управління пам'яттю, а натомість вони вважають за краще використовувати сміття (GC).

Я вважаю це досить заплутаним, оскільки

  1. SBMM робить програми більш детермінованими (ви можете точно сказати, коли об’єкт знищений);
  2. у мовах, які використовують GC, вам часто доводиться вручну керувати ресурсами (див., наприклад, закриття файлів на Java), що частково перешкоджає призначенню GC, а також є схильними до помилок;
  3. Купі пам'ять також може бути (дуже елегантно, imo) обмежена сферою дії (див. std::shared_ptrу C ++).

Чому SBMM не використовується ширше? Які його недоліки?


1
Деякі недоліки (особливо щодо швидкості) обговорюються у Вікіпедії: en.wikipedia.org/wiki/…
Філіп

2
Проблема управління ресурсами в Java в якості побічного ефекту - це не гарантія того, що метод об'єкта finalize()буде викликаний перед вивезенням сміття. Фактично, це створює той самий клас проблем, що і вирішення сміття.
Blrfl

7
@Blrfl Дурниці. "Ручне" управління ресурсами (очевидно, для інших ресурсів, ніж пам'ять) було б кращим, навіть якщо б ця "проблема" не існувала, оскільки GC може працювати дуже довго після того, як ресурс стане невикористаним, або взагалі не працює. Це не проблема для пам’яті , а управління пам’яттю - це все, що має вирішувати збирання сміття.

4
btw. Мені подобається називати це SBRM, оскільки ви можете використовувати один і той же механізм для управління ресурсами взагалі, а не лише пам'яттю.
ПлазмаHH

Відповіді:


27

Почнемо з постулювання, що пам'ять на сьогоднішній день (десятки, сотні чи навіть тисячі разів) частіше, ніж усі інші ресурси разом. Кожна окрема змінна, об’єкт, член об'єкта потребує виділеної йому пам'яті та звільненої пізніше. Для кожного відкритого файлу ви створюєте десятки до мільйонів об'єктів для зберігання даних, витягнутих з файлу. Кожен потік TCP поєднується з необмеженою кількістю тимчасових байтових рядків, створених для запису в потік. Ми тут на одній сторінці? Чудово.

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

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

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

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

Ваш другий пункт, ручне управління ресурсами, сьогодні вирішується за допомогою заяви, яка виконує очищення, засноване на масштабах, але не прив'язує це очищення до часу життя об'єкта (отже, не взаємодіючи з GC та безпекою пам'яті). Це usingв C #, withв Python, try-з ресурсами в останніх версіях Java.


1
Це не пояснює, чому недетерміновані моделі, такі як GC, повинні перевершувати детерміновані. usingзаяви можливі лише локально. Таким чином неможливо очистити ресурси, що містяться в змінних членів.
Філіп

8
@Philipp Спільне право власності на все - це GC, просто дуже бідне. Якщо ви вважаєте, що "спільна власність" передбачає підрахунок посилань, будь ласка, скажіть так, але продовжуйте обговорювати цикли у коментарях до відповіді Амона. Я також не впевнений, чи є підрахунок посилань детермінованим у тому сенсі, що цікавить ОП (об'єкти звільняються як можна раніше, дисконтування циклів, але ви часто не можете сказати, коли це, переглянувши програму). Більше того, підрахунок посилань на все проходить повільно, набагато повільніше, ніж сучасний GC.

16
usingце жарт у порівнянні з RAII, просто так ви знаєте.
DeadMG

3
@Philipp, будь ласка, опишіть свою метрику для "вище" Це правда, що ручне управління пам’яттю швидше під час виконання роботи з управлінням пам’яттю. Однак про вартість програмного забезпечення не можна судити лише про час процесора, витрачений лише на управління пам'яттю.
ArTs

2
@ArTs: Я б навіть не обов'язково з цим погоджувався. RAII поставляється з вимогою, що об'єкт повинен бути знищений, оскільки він залишає область. Тоді петля потрібна для руйнування n об'єктів. За сучасного покоління GC ці руйнування можуть бути відкладені до кінця циклу, а то й пізніше, і виконати лише одну операцію, щоб знищити сотні ітерацій, варті пам'яті. GC може бути дуже швидким у своїх хороших випадках.
Фоши

14

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

Мови, зібрані сміттям, не можуть використовувати RAII безпосередньо, але часто пропонують синтаксис з аналогічним ефектом. У Java у нас є оператор "спробувати рессурси"

try (BufferedReader br = new BufferedReader(new FileReader(path))) { ... }

який автоматично викликає .close()ресурс при виході з блоку. У C # є IDisposableінтерфейс, який дозволяє .Dispose()викликати, залишаючи using (...) { ... }заяву. У Python є withтвердження:

with open(filename) as f:
    ...

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

File.open(name, mode) do |f|
    ...
end

Я думаю, що Node.js використовує ту саму стратегію.


4
Використання функцій вищого порядку для управління ресурсами датується задовго до Рубі. У Lisps досить часто існують, скажімо, with-open-filehandleфункції, які відкривають файл, приводять його у функцію, а після повернення функції знову закривають файл.
Йорг W Міттаг

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

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

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

1
Важливою причиною, чому підрахунок посилань використовується рідко, є те, що він часто повільніше, ніж GC, незважаючи на його простоту.
Rufflewind

14

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

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

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


1
Коректність поєднується лише у тому випадку, якщо об’єкти мають посилання лише від свого імені, а не від імені цілей цих посилань. Після того, як такі речі, як сповіщення, входять в суміш (Боб посилається на Джо, тому що Джо попросив Боба повідомити його, коли щось трапилося, і Боб пообіцяв це зробити, але Боб інакше не переймається Джо), коректність GC часто вимагає керованого управління ресурсами [вручну реалізований у багатьох випадках, оскільки системам GC не вистачає автоматизації C ++].
supercat

@supercat: "Правильність GC часто вимагає управління масштабними ресурсами". Так? Область застосування існує лише у вихідному коді, а GC існує лише під час виконання (і, отже, повністю не враховує існування області).
Джон Харроп

@JonHarrop: Я використовував термін "область" в тому ж сенсі, що і C ++ "скопійований покажчик" (термін експлуатації об'єкта повинен бути тривалим у контейнері, який утримує його), оскільки це використання, яке має на увазі вихідний питання. Моя думка полягає в тому, що об’єкти створюють потенційно довговічні посилання на себе для таких цілей, як отримання подій, можливо, не можна поєднувати в суто GC-системі. Для коректності певні посилання повинні бути чіткими, а деякі посилання повинні бути слабкими, а посилання повинні бути, які залежатимуть від використання об'єкта. Наприклад ...
supercat

... припустимо, що об'єкти Фред і Барні підписуються на повідомлення щоразу, коли щось у певному каталозі буде змінено. Обробник Фреда не робить нічого, крім збільшення лічильника, про значення якого він може повідомити на запит, але для якого він не має іншого використання. Обробник Barney з'явиться нове вікно, якщо певний файл буде змінено. Для коректності Фреду слід передплатити слабку подію, але Барні повинен бути сильним, але об'єкт таймера не зможе цього знати.
supercat

@supercat: Правильно. Я б не сказав, що це трапляється "часто". Я натрапив на це лише раз за 30 років програмування.
Джон Харроп

7

Закриття є важливою особливістю майже всіх сучасних мов. Їх дуже просто реалізувати за допомогою GC і дуже важко (хоча і не неможливо) отримати правильний результат з RAII, оскільки одна з головних їх особливостей полягає в тому, що вони дозволяють абстрагуватися протягом усього життя змінних!

C ++ отримав їх лише через 40 років після того, як всі інші зробили, і для того, щоб їх правильно виправити, потрібно було багато важкої роботи. На відміну від багатьох мов сценаріїв, розроблених та впроваджених людьми з нульовими знаннями в розробці та реалізації мов програмування, є їх.


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

Я погоджуюся з delnan: C ++ не отримав права закриття: ви повинні запрограмувати їх дуже обережно, якщо ви не хочете отримати основний дамп, коли ви викликаєте їх.
Джорджіо

2
@delnan: лямбда-захоплення за посиланням дуже навмисно має цей [&]синтаксис. Будь-який програміст на C ++ вже пов'язує &знак із посиланнями та знає про несвіжі посилання.
MSalters

2
@MSalters Який твій погляд? Я сам намалював опорне з'єднання. Я не сказав, що лямбди C ++ є виключно небезпечними, я сказав, що вони такі ж небезпечні, як і посилання. Я не заперечував, що лямбди C ++ погані, я стверджував проти твердження цієї відповіді (що C ++ закінчився дуже пізно, тому що їм довелося зрозуміти, як це зробити правильно).

5
  1. SBMM робить програми більш детермінованими (ви можете точно сказати, коли об’єкт знищений);

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

  1. у мовах, які використовують GC, вам часто доводиться вручну керувати ресурсами (див., наприклад, закриття файлів на Java), що частково перешкоджає призначенню GC, а також є схильними до помилок;

Дивіться usingв C # і useF #.

  1. Купа пам’яті також може (дуже елегантно, imo) бути обмеженою сферою (див. std :: shared_ptr в C ++).

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

Чому SBMM не використовується ширше? Які його недоліки?

SBMM обмежує те, що ви можете зробити:

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

  2. SBMM вимагає деструкторів, і вони перешкоджають виклику хвостів, додаючи більше роботи, перш ніж функція може повернутися. Хвостові дзвінки корисні для машин, що розширюються, і надаються такими речами, як .NET.

  3. Деякі структури даних та алгоритми, як відомо, важко реалізувати за допомогою SBMM. В основному де завгодно, що цикли відбуваються в природі. Найбільше графічних алгоритмів. Ви фактично закінчуєте писати свій власний GC.

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

  5. SBMM зберігає об’єкти живими до кінця їх сфери дії у вихідному коді, який часто довший необхідного і може бути набагато довшим, ніж потрібно. Це збільшує кількість плаваючого сміття (недоступних об’єктів, які чекають переробки). На противагу цьому, відстеження сміття, як правило, звільняє об'єкти незабаром після зникнення останнього посилання на них, що може бути набагато швидше. Дивіться міфи про управління пам'яттю: оперативність .

SBMM настільки обмежує, що програмістам потрібен маршрут евакуації в ситуаціях, коли життя не може бути здійснено до гніздування. У програмі C ++ shared_ptrпропонується шлях втечі, але це може бути на 10 разів повільніше, ніж відстеження сміття . Тож використання SBMM замість GC спричиняло б більшість людей неправильно. Однак це не означає, що це марно. SBMM як і раніше є цінним у контексті систем та вбудованих програм, де ресурси обмежені.

FWIW, можливо, ви хочете перевірити Форта та Ада і прочитати твір Ніколя Вірта.


1
Якщо ви скажете, які біти я можу розробити чи цитувати статті.
Джон Харроп

2
Наскільки доречно бути в 10 разів повільніше у кількох рідкісних випадках використання, на відміну від всюдисущого у всіх випадках використання? C ++ має унікальний_ptr і для більшості цілей достатній. Поруч із цим, замість того, щоб атакувати RAII через C ++ (мова, яку багато хто любить ненавидіти за архаїчну мову), якщо ви збираєтесь напасти на RAII через атаку на мову, спробуйте молодший брат рідних RAII, наприклад Руст. Іржа, як правило, отримує все в порядку, що C ++ помилився, тоді як більшість речей правильно, що і C ++, виправдалися. Подальше "використання" отримує дуже обмежений набір випадків використання та ігнорує склад.
user1703394

2
"Наскільки релевантним є на 10 разів повільніше у кількох рідкісних випадках використання, на відміну від всюдисущого у всіх випадках використання?". По-перше, це круговий аргумент: shared_ptrвін рідкісний лише в C ++, оскільки він настільки повільний. По-друге, це порівняння яблук і апельсинів (як уже було показано в статті, яку я цитував), тому що shared_ptrце в багато разів повільніше, ніж виробничий GC. По-третє, GC не є всюдисущими та їх уникають у таких програмних програмах, як LMax та FIX двигун Rapid Addition.
Джон Харроп

1
@ Jon Harrop, Якщо ти не будь ласка, просвіти мене. Який чарівний рецепт ви використовували протягом 30+ років для пом’якшення перехідних наслідків використання глибоких ресурсів? Без такого чарівного рецепту через 30+ років я міг лише зробити висновок, що ви, мабуть, неправильно розподілили, щоб його вкусили на інші причини.
user1703394

1
@Jon Harrop, shared_ptr не є рідкістю, оскільки його повільність, рідкість з тієї причини, що в пристойно розробленій системі потреба у «спільній власності» є рідкісною.
користувач1703394

4

Дивлячись на якийсь індекс популярності на зразок TIOBE (який, звичайно, є спірним, але, мабуть, для вашого типу питань його нормально використовувати), ви спочатку бачите, що ~ 50% перших 20 - це "мови сценаріїв" або "діалекти SQL" ", де" простота використання "та засоби абстракції мають набагато більше значення, ніж детермінована поведінка. З решти "складених" мов залишилося близько 50% мов із SBMM і ~ 50% без. Тож, виймаючи мови мовлення сценаріїв з вашого розрахунку, я б сказав, що ваше припущення просто неправильне, серед мов, що складаються, ті, які мають SBMM, такі ж популярні, як і без них.


1
Чим "простота використання" відрізняється від детермінізму? Чи не можна визначити детерміновану мову простішою у використанні, ніж недетерміновану?
Філіп

2
@Philipp Тільки те, що детерміновано чи насправді не має значення. Життєвий час об’єкта не має значення сам по собі (хоча C ++ та друзі пов’язують багато речей, які мають значення для того, щоб заперечити час життя, оскільки вони можуть). Коли звільнений недоступний об'єкт не має значення, оскільки, за визначенням, ви його більше не використовуєте.

Ще одне, різні "мови скриптування", такі як Perl і Python, також використовують підрахунок посилань як основний засіб управління пам'яттю.
Філіпп

1
@Philipp Принаймні у світі Python це вважається деталізацією реалізації CPython, а не властивістю мови (і практично будь-яка інша реалізація відмовляється від перерахунку). Більше того, я заперечую, що підрахунок опорного відключення без відключення з циклом резервного копіювання GC не кваліфікується як SBMM або RAII. Насправді, вам буде важко знайти прихильників RAII, які вважають цей стиль управління пам'яттю порівнянним з RAII (здебільшого тому, що це не так, цикли в будь-якому місці можуть запобігти оперативному розміщенню місця в будь-якому іншому місці програми).

3

Однією з головних переваг системи GC, про яку ще ніхто не згадував, є те, що посилання в системі GC гарантовано зберігає свою ідентичність до тих пір, поки вона існує . Якщо хтось викликає IDisposable.Dispose(.NET) або AutoCloseable.Close(Java) на об'єкті, коли існують копії посилання, ці копії продовжуватимуть посилатися на той самий об’єкт. Об'єкт більше не буде корисним, але спроби його використовувати матимуть передбачувану поведінку, керовану самим об'єктом. Навпаки, в C ++, якщо код викликає deleteоб’єкт і пізніше намагається його використовувати, весь стан системи стає абсолютно невизначеним.

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


4
Властивість, на яку ви посилаєтесь у першій половині, - це безпека пам’яті. Хоча GC - це дуже простий спосіб досягти безпеки пам’яті, GC не потрібен: Подивіться на Руста за добре зробленим прикладом.

@delnan: Коли я переглядаю rust-lang.org, мій браузер не може здатися звідти корисним навігацією; де мені шукати додаткову інформацію? Моє враження полягає в тому, що безпека пам’яті без GC накладає певні обмеження на структуру даних, які можуть не відповідати всім речам, які може знадобитися програма, але я буду радий помилятися.
supercat

1
Я не знаю жодного (або навіть невеликого набору) хороших посилань на це; мої знання про іржу накопичилися за рік-два читання списку розсилки (і всі речі, пов’язані з електронною поштою, включаючи різні підручники, публікації в блогах з мовного дизайну, випуски github, ThisWeekInRust тощо). Якщо коротко вирішити своє враження: Так, кожна безпечна конструкція (обов’язково) встановлює обмеження, але практично для будь-якого захищеного пам'яті фрагмента коду існує або може бути записана відповідна безпечна конструкція. На сьогодні найпоширеніші з них вже існують у мові та stdlib, усі інші можуть бути записані в коді користувача.

@delnan: Чи потрібні Rust блоковані оновлення до лічильників посилань, чи є у неї інші способи поводження з незмінними об'єктами (або незмінними оберненими змінними об'єктами), які не мають певного права власності? Чи має у Русті поняття як "власників об'єктів", так і "невласників"? Я пригадую документ про покажчики "Xonor", в якому обговорювались ідеї об'єктів, що мають єдину посилання, яка "володіє ними", та інші посилання, які не мають; коли посилання на "володіння" виходить за межі, всі невласні посилання стануть посиланнями на мертві об'єкти, і їх можна було б ідентифікувати як такі ...
supercat

1
Я не думаю, що коментарі Stack Exchange є правильним засобом для проведення екскурсії через мову. Якщо вам все-таки цікаво, ви можете перейти безпосередньо до джерела (#rust IRC, список розсилки з іржею-розробником тощо) та / або зав'язати мене в чаті (ви повинні мати можливість створити його).

-2

По-перше, дуже важливо усвідомити, що прирівнюють RAII до SBMM. або навіть до СБРМ. Однією з найважливіших (і найменш відомих або найбільш недооцінених) якостей RAII є той факт, що він робить «бути ресурсом» властивістю, яка НЕ ​​переходить до складу.

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

http://minorfs.wordpress.com/2011/04/29/why-garbage-collection-is-anti-productive/

Важливо зазначити, що в той час, як RAII використовується в основному в C ++, Python (нарешті, версія, що не заснована на ВМ) має деструктори та детерміновані GC, що дозволяє використовувати RAII разом із GC. Краще з обох світів, якби воно було.


1
-1 Це одна з найгірших статей, яку я коли-небудь читав.
Джон Харроп

1
Проблема мов полягає не в тому, що вони підтримують GC, а в тому, що вони відмовляються від RAII. Немає жодної причини, що мова / рамки не повинні підтримувати обох.
supercat

1
@Jon Harrop, ви могли б детальніше розібратися. Чи існує одна з перших 3 заяв, яка не відповідає? Я думаю, ви можете не погодитись із заявою про продуктивність, але інші 3 твердження абсолютно справедливі. Найголовніше перше про транзитивність буття ресурсу.
user1703394

2
@ user1703394: По-перше, вся стаття базується на солом'яному "мові GCed", коли насправді це не має нічого спільного зі збиранням сміття. По-друге, він звинувачує вивезення сміття, коли насправді несправності полягають у об'єктно-орієнтованому програмуванні. Нарешті, його аргумент на 10 років занадто пізно. Переважна більшість програмістів вже модернізували сміття зібраними мовами саме тому, що вони пропонують набагато більшу продуктивність.
Джон Харроп

1
Його конкретні приклади (оперативна пам'ять, ручки відкритого файлу, замки, нитки) є досить показовими. Мені важко згадати, коли останній раз мені довелося писати код, який стосувався безпосередньо будь-якого з них. За допомогою оперативної пам’яті GC автоматизує все. За допомогою ручок файлів я пишу код, як, наприклад, File.ReadLines file |> Seq.lengthде абстракції обробляють для мене закриття. Замки та нитки я замінив на .NET Taskі F # MailboxProcessor. Весь цей "Ми вибухнули кількість ручного управління ресурсами" - це просто повна дурниця.
Джон Харроп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.