Чистая и неотключающая функция, которая не выдает память, автоматически собирает мусор?

Предположим, у вас есть функция в D, которая является pure и nothrow и по типу возвращаемого значения и типам аргументов не может выдать какую-либо вновь выделенную память. Могу ли я тогда добавить к этой функции атрибут @nogc? Если нет, есть ли шансы, что это станет возможным в будущем?

Моя точка зрения здесь следующая: поскольку функция не имеет видимых побочных эффектов, вся память, которая была выделена на пути, может быть детерминировано освобождена при выходе из функции. Следовательно, GC на самом деле не требуется, так как можно избежать шага маркировки и развертки. Или нельзя?


person Ralph Tandetzky    schedule 22.12.2015    source источник


Ответы (2)


Вы всегда можете попробовать добавить @nogc и скомпилировать. Чистая функция может по-прежнему выделять внутренние буферы, даже если она не возвращает ни один из них, поэтому вопрос сборки мусора находится на другой оси, чем чистота.

Если он проходит компиляцию с @nogc, он не будет выделять (и, следовательно, не собирать, D GC будет собирать только тогда, когда вы попросите его выделить) независимо от чистоты.

person Adam D. Ruppe    schedule 22.12.2015
comment
Спасибо за быстрый ответ, но я думаю, что вы упустили мою мысль. Поэтому я уточнил свой вопрос, добавив еще немного текста. - person Ralph Tandetzky; 23.12.2015
comment
Ах, да, чистая функция теоретически должна иметь возможность использовать распределитель области для всего своего стека вызовов со свободным в конце, хотя я не ожидаю, что это будет реализовано автоматически в ближайшее время... - person Adam D. Ruppe; 23.12.2015
comment
Или всегда можно было выделить в стеке и забыть об освобождении памяти? - person Tamas; 23.12.2015
comment
@Tamas Я не думаю, что это сработает, потому что часть выделенной памяти должна оставаться в живых дольше, чем функция, которая ее выделила. Это не работает с распределением стека. Хотя это может быть второй стек. - person Ralph Tandetzky; 23.12.2015
comment
@AdamD.Ruppe Может быть, я здесь немного зеленый, но реализация такой функциональности не кажется слишком сложной: рассматриваемая функция должна переключить локальный флаг потока в сборщике мусора, сообщая ему о выделении в регионе. распределитель, а затем функция должна очистить после себя в конце. Единственное, о чем я бы беспокоился, — это выделение памяти в узких циклах, которые производят слишком много мусора. Но опять же, сборка мусора может выполняться локально, что намного эффективнее, чем глобальная сборка. - person Ralph Tandetzky; 23.12.2015
comment
Да, второй стек — это более или менее распределитель регионов. Это не должно быть слишком сложно, но нужно быть осторожным. Возможно, флаг будет счетчиком, который добавляется и вычитается из него, может обрабатывать произвольную глубину этих строго чистых функций, и компилятор будет включать и отключать его при входе в функцию /выход. Оттуда гарантии immutable+pure вместе с возвращаемым значением, не имеющим косвенности, должны быть достаточными, чтобы гарантировать отсутствие ускользающих ссылок, но они должны быть сильно чистыми снаружи, слабо чистые могут все еще возвращаться через наши детские коляски. Затем druntime использует регион и освобождает @ cnt==0. - person Adam D. Ruppe; 23.12.2015

https://dlang.org/spec/attribute.html#nogc

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

Он ничего не говорит о состоянии GC после выполнения функции или увеличении общего использования памяти. Единственное, что имеет значение, это то, что сама функция гарантированно никогда не вызовет какие-либо функции распределения GC, т. е. вы можете надежно построить и запустить такую ​​функцию с пользовательской средой выполнения, которая вообще не связана с реализацией GC.

Еще одним важным моментом является то, что оптимизация не может повлиять на @nogc, потому что один и тот же правильный код должен продолжать компилироваться с разными уровнями оптимизации и разными компиляторами. Любые такие оптимизации должны стать обязательными в спецификации языка, прежде чем @nogc сможет их использовать.

Учитывая все это, описанная вами функция может получить действительную аннотацию @nogc только в том случае, если выполняются оба следующих условия:

  1. на самом деле он вообще не делает никаких вызовов GC, он полностью оптимизирован
  2. такая оптимизация обязательна и гарантированно всегда происходит в таких случаях для всех совместимых компиляторов по спецификации языка

Я вижу это крайне маловероятным.

person Mihails Strasuns    schedule 23.12.2015
comment
Это правильно с текущим определением @nogc. Но, с другой стороны, можно было бы переопределить значение @nogc, чтобы оно означало, что никакого глобального замораживания мира не произойдет и что сборщик мусора будет находиться в том же состоянии после вызова функции, что и в функции at. Вход. С этим измененным определением это вполне возможно. - person Ralph Tandetzky; 23.12.2015
comment
Учитывая, что @nogc был в первую очередь представлен для привлечения разработчиков игр и встроенной аудитории, я ожидаю, что такая попытка встретит довольно сильное сопротивление. - person Mihails Strasuns; 23.12.2015