Время жизни Nativecall Buf и сборщик мусора - PullRequest
6 голосов
/ 17 марта 2019

У меня есть кусок памяти в Buf Я хочу передать в библиотеку C, но библиотека будет использовать память по истечении времени жизни одного вызова.

Я понимаюэто может быть проблематично, так как сборщик мусора может перемещать память.

Для передачи Str, документы Nativecall говорят «Если функция C требует, чтобы время жизни строки превышаловызов функции, аргумент должен быть закодирован вручную и передан как CArray [uint8] "и иметь пример для этого, по сути:

my $array = CArray[uint8].new($string.encode.list);

Мой вопрос: должен ли я сделать то же самое для Buf?В случае, если это будет перемещено GC?Или GC оставит мой Buf там, где он сидит?Для короткой строки это не имеет большого значения, но для большого буфера памяти это может быть дорогостоящей операцией.(См., Например, Archive :: Libarchive , который вы можете передать в Buf с файлом tar. Этот код проблематичен?

multi method open(Buf $data!) {
    my $res = archive_read_open_memory $!archive, $data, $data.bytes; 
    ...

Есть (может быть«Должно ли быть?) что-то вроде trait на Buf, который говорит GC не перемещать его? Я знаю, что это может быть проблемой, если я добавлю больше данных в Buf, но я обещаю не делатьчто. Как насчет Blob, который является неизменным?

1 Ответ

6 голосов
/ 23 марта 2019

Это сойдет вам с рук на MoarVM, по крайней мере, на данный момент, при условии, что вы сохраните ссылку на Blob или Buf в Perl 6 до тех пор, пока это требуется нативному коду и (в в случае Buf) вы не пишете в него, что может привести к изменению размера.

MoarVM выделяет объект Blob / Buf внутри детской и перемещает его во время прогонов ГХ. Однако этот объект не содержит данных; скорее он содержит размер и указатель на блок памяти, содержащий значения. Этот блок памяти не выделяется с помощью GC и поэтому не будет перемещаться.

+------------------------+
| GC-managed Blob object |
+------------------------+      +------------------------+
| Elements               |----->| Non-GC-managed memory  |
+------------------------+      | (this bit is passed to |
| Size                   |      | native code)           |
+------------------------+      +------------------------+

Стоит ли полагаться на это, это более сложный вопрос. Некоторые соображения:

  • Насколько я могу судить, все могло бы пойти не так хорошо, если бы я работал на JVM. Я не знаю о бэкэнде JavaScript. Вы могли бы на законных основаниях решить, что из-за уровней усыновления вам пока придется беспокоиться только о работе на MoarVM.
  • В зависимости от деталей реализации MoarVM вполне подходит, если вам просто нужна скорость в вашем собственном коде, но если вы работаете над модулем, который вы ожидаете получить широкое распространение, вы можете подумать, стоит ли это того. Команды Rakudo и MoarVM проделали большую работу, чтобы не регрессировать рабочий код в модульной экосистеме, даже в тех случаях, когда можно утверждать, что он зависел от ошибок или неопределенного поведения. Однако это может заблокировать улучшения. Кроме того, в некоторых случаях поломка считается стоящей. В любом случае, это отнимает много времени и ложится на команду добровольцев. Конечно, когда авторы модулей отзывчивы и могут применять предоставленные исправления, это несколько меньше проблем.

Проблема с «положением черты» заключается в том, что решение - по крайней мере, относительно JVM - кажется, должно быть принято заранее, когда выделяется память, содержащая данные. В этом случае переносимое решение, вероятно, не может позволить пометить существующий Buf / Blob как таковой. Возможно, лучшим способом будет то, что объекты ввода-вывода будут запрашивать что-то вроде CArray, так что нулевое копирование может быть достигнуто при наличии данных в «правильном виде памяти» в первую очередь. , Это, вероятно, разумный запрос на добавление функций.

...