LINUX.ORG.RU

Этот ваш reference counting

 ,


1

4

Во время попытки доказать одному товарищу, что Swift — ненужно, я наткнулся на интересную особенность:

import Foundation

let noLeak = 131028
let withLeak  = noLeak*10

class R {
    var _a : R?
    init(a : R?) {
        _a = a
    }
}

func test(n:Int, leak:Bool) {
    var p0 = R(a : nil)
    var p = R(a : p0)
    for _ in 1...n {
        p = R(a : p)
    }
    if leak {
        p0._a = p
    }
}

test(withLeak, true)
println("Evil leaking function")
test(noLeak, false)
println("Good function")

Первый вызов test просто течёт в лучших традициях Reference Counting, а вот второй падает со stack overflow (деаллокация, похоже, делается рекуррентно).

Интересно, есть ли такое же в Rust?


Это валится каскадный релиз, до деаллокации дело не доходит. Так и связный список на сях может повалиться, если void list_free(list) { list_free(next); free(list); } или наоборот + нет tco. В чем доказательство ненужности не совсем понятно.

anonymous ()

Хотел удивить циклическими ссылками @ план провалился.

quiet_readonly ★★★★ ()
Ответ на: комментарий от anonymous

Это валится каскадный релиз, до деаллокации дело не доходит.

Верно. Но как же работать с рекурсивными типами с этим reference counting? ГЦ, к примеру, такие вещи соберёт.

fmdw ()

Занятно, надо будет попробовать. Язык-то хороший.

Miguel ★★★★★ ()
Ответ на: комментарий от fmdw

План не провалился, скорее наоборот.

То есть слушатель использовал Swift и не знал, что такое циклические ссылки? Обоссать его надо бы.

quiet_readonly ★★★★ ()
Ответ на: комментарий от fmdw

Верно. Но как же работать с рекурсивными типами с этим reference counting? ГЦ, к примеру, такие вещи соберёт.

Для реальных задач на это придуманы как weak, так и unsafe_unretained. К тому же тут не просто рекурсивный тип, тут именно циклический.

quiet_readonly ★★★★ ()
Ответ на: комментарий от anonymous

Поскольку сишка кучу вообще сама не чистит, этот пример на ней можно написать, раскрутив хвостовой вызов вручную. А что делать в «умных» языках, я что-то ума не приложу.

fmdw ()
Ответ на: комментарий от quiet_readonly

К тому же тут не просто рекурсивный тип, тут именно циклический.

Wut?

fmdw ()
Ответ на: комментарий от fmdw

Не использовать умную часть. Наверняка если копнуть доки, то найдешь либо POD, либо бриджинг-ретайн для случаев unsafe_unretained (сам не смотрел). Если нет, тогда «по-старинке» на объективе/мрц и импортируй, делов-то.

anonymous ()
Ответ на: комментарий от anonymous

То есть даже элементарный список без специальных костылей не пишется? Заепца, чо.

anonymous ()
Ответ на: комментарий от fmdw

Я кстати скорее всего туплю, но тоже ума не приложу, как без тсо раскрутить связный список не превышая O(1) по памяти и/или O(n) по итерациям.

anonymous ()

А можешь описать/от комментировать код? А то синтаксис непонятный. Что тут происходит?

anonymous ()
Ответ на: комментарий от fmdw

ГЦ, к примеру, такие вещи соберёт.

Ну и что? Огромной ценой соберет такие, но от утечек всё равно полностью не избавит. Многолетний опыт показал, что невозможно придумать такую технологию, которая позволит любой обезьяне быть программистом, приходя всякий раз на помощь, когда ей захочется побыть ССЗБ обезьяной.

asaw ★★★★★ ()
Ответ на: комментарий от anonymous

Что? Если у тебя хвостовой вызов, то значит ты легко напишешь итеративный вариант.

anonymous ()
Ответ на: комментарий от anonymous

Создается куча циклически связанных объектов (в зависимости от флажка).

asaw ★★★★★ ()

Интересно, есть ли такое же в Rust?

В rust ты не сможешь без извращений сделать

p0._a = p
т.к. для этого нужен mutable borrow, а его нельзя сделать, т.к. уже был взят immutable borrow на строчке
var p = R(a : p0)

maloi ★★★★★ ()
Ответ на: комментарий от asaw

Ну и что? Огромной ценой соберет такие, но от утечек всё равно полностью не избавит.

Соберет за O(0) и от утечек избавит, конечно же.

anonymous ()
Ответ на: комментарий от asaw

Во всех рабочих реализациях GC находит доступные объекты, а все остальное считает мусором. Поэтому собрать такое проще простого, а вот если у тебя такой объект живет долго, то будут проблемы при каждой сборке.

maloi ★★★★★ ()
Ответ на: комментарий от anonymous

Если при этом ещё и память не жрал, цены бы ему не было.

nezamudich ★★ ()

Я вот чего понять не могу. Разве я ошибаюсь в том, что Swift нацелен на «обычную» десктопную разработку под яблочные ОСи(а значит предполагает простую разработку и большое сообщество легкозаменяемых разработчиков)? А если не ошибаюсь, то мне совершенно неясно, зачем отказываться от сборки мусора.

forCe ()
Ответ на: комментарий от asaw

Ну получить утечки при наличии сборки мусора гораздо сложнее.

forCe ()
Последнее исправление: forCe (всего исправлений: 1)
Ответ на: комментарий от fmdw

Поскольку сишка кучу вообще сама не чистит, этот пример на ней можно написать, раскрутив хвостовой вызов вручную. А что делать в «умных» языках, я что-то ума не приложу.

Не писать низкоуровневые структуры на Swift? Удобная интеграция Objective-C с C/C++ сделана не для того, чтобы кто-то назло маме морозил уши, помочившись на шапку.

quiet_readonly ★★★★ ()
Ответ на: комментарий от forCe

А если не ошибаюсь, то мне совершенно неясно, зачем отказываться от сборки мусора.

Затем, что кроме удаления таких вот связных списков он ничего большего, чем ARC, не умеет.

quiet_readonly ★★★★ ()
Ответ на: комментарий от forCe

Ну получить утечки при наличии сборки мусора гораздо сложнее.

Приличную скорость тоже.

quiet_readonly ★★★★ ()
Ответ на: комментарий от quiet_readonly

Приличную скорость тоже.

Хотелось бы пруф на то, что языки с ARC быстрее/медленнее, чем с полноценным GC.

hateyoufeel ★★★★★ ()
Ответ на: комментарий от nezamudich

Если при этом ещё и память не жрал, цены бы ему не было.

Память жрет приложение, а не сборщик.

anonymous ()
Ответ на: комментарий от quiet_readonly

Затем, что кроме удаления таких вот связных списков он ничего большего, чем ARC, не умеет.

А что, удаление больших структур данных - это НИНУЖНО?

anonymous ()
Ответ на: комментарий от hateyoufeel

Хотелось бы пруф на то, что языки с ARC быстрее/медленнее, чем с полноценным GC.

Смотря какой гц. Если хороший, компактифицирующий generational сборщик - он на порядок быстрее подсчета ссылок работает (и даже быстрее ручного управления памятью, если не писать собственные аллокаторы).

anonymous ()
Ответ на: комментарий от anonymous

Смотря какой гц. Если хороший, компактифицирующий generational сборщик - он на порядок быстрее подсчета ссылок работает (и даже быстрее ручного управления памятью, если не писать собственные аллокаторы).

Это очень интересный вопрос, на самом деле. Погуглив, я нашел вот это (http://www.lshift.net/blog/2013/09/19/the-great-gc-vs-reference-counting-debate/), но там это обсуждается приминительно к браузерам и Obj-C.

Из личного опыта, GC отлично сочетается с immutable-структурами. В Haskell и Erlang, с которыми я работаю, со скоростью GC проблем нет, и код на Haskell работает в пределах одного порядке с кодом на C++.

С другой же стороны есть Java, от мысли о производительности которой хочется залезть под кровать и рыдать кровавыми слезами.

А вот годных реализаций ARC я пока не встречал, потому как все они текут как сучки.

hateyoufeel ★★★★★ ()
Ответ на: комментарий от quiet_readonly

Хотел удивить циклическими ссылками @ план провалился.

А расскажи, что за болезнь пошла писать этот бред вместо «Хотел удивить циклическими ссылками & план провалился.» или хотя бы «План провалился@ хотел удивить циклическими ссылками.»? Кто вас покусал?

t184256 ★★★★★ ()
Ответ на: комментарий от anonymous

O(0)

В программировании уже такое изобрели?

anonymous ()
Ответ на: комментарий от quiet_readonly

Надо добавить в мудрые изречения диванных теоретиков ЛОРа. Есть же у вас тут такой сайт?

anonymous ()
Ответ на: комментарий от anonymous

O(0)

В программировании уже такое изобрели?

исключительно на лоре, сэр

unt1tled ★★★★ ()
Ответ на: комментарий от parrto

как сконпелять-то?

В XCode кнопочку тыцкнуть, ты прям как натурал :)

ovk48 ★★★ ()
Ответ на: комментарий от maloi

Давайте забудем про пример с циклическими ссылками. Я спрашивал, как в ржавчине обработается более простой случай, где их нет.

fmdw ()
Ответ на: комментарий от anonymous
void listFree(List *a) {
  List *b;
  while(a) {
    b = a.next;
    free(a);
    a = b;
  }
}

?

fmdw ()
Ответ на: комментарий от ovk48

ну я так и понял, что это канал про аниме. О времена, о нравы

parrto ()
Ответ на: комментарий от hateyoufeel

код на Haskell работает в пределах одного порядке с кодом на C++.

В смысле до 10 раз медленнее? Жабка-то пошустрее будет.

anonymous ()
Ответ на: комментарий от anonymous

В смысле до 10 раз медленнее? Жабка-то пошустрее будет.

В среднем - около 2 раз. Можно, конечно, код оптимизировать, но пока не нужно было.

hateyoufeel ★★★★★ ()
Ответ на: комментарий от maloi

Во всех рабочих реализациях GC находит доступные объекты, а все остальное считает мусором. Поэтому собрать такое проще простого

Во всех рабочих реализациях нужно пройтись по всем объектам минимум один раз. Поэтому толсто.

asaw ★★★★★ ()
Ответ на: комментарий от quiet_readonly

Затем, что кроме удаления таких вот связных списков он ничего большего, чем ARC, не умеет.

Он много чего умеет(некоторые алгоритмы плохо реализуются без сборки мусора). Кроме того, он лишён тормозов arc. У arc очень дорогие операции копирования ссылок, а так же обработки выхода за scope.

anonymous ()
Ответ на: комментарий от asaw

Если мы учтем поколения и другие плюшки современных gc, то все будет не так плохо. Arc, в большинстве случаев, тормознее, чем реализация с gc.

anonymous ()
Ответ на: комментарий от quiet_readonly

Так GC быстрее ARC. Плюшки ARC не в скорости, а в детерминированном удалении и меньшем расходе памяти системы.

anonymous ()
Ответ на: комментарий от asaw

Во всех рабочих реализациях нужно пройтись по всем объектам минимум один раз.

Зачем?

hateyoufeel ★★★★★ ()
Ответ на: комментарий от quiet_readonly

Не писать низкоуровневые структуры на Swift?

Зачем нужны языки, на которых нельзя (или опасно) писать валидные программы?

fmdw ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.