Nativecall Buf生存期和垃圾收集器

问题描述 投票:6回答:1

我在Buf中有一大块内存我要传递给C库,但是库将使用超过单个调用生命周期的内存。

我知道这可能有问题,因为垃圾收集器可以移动内存。

为了传入StrNativecall docs说“如果C函数要求字符串的生命周期超过函数调用,则必须手动编码参数并将其作为CArray [uint8]传递”并且有一个这样做的示例,基本上:

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

我的问题是:我必须为Buf做同样的事吗?万一它被GC移动了?或者GC会将我的Buf留在原处吗?对于一个短字符串,这不是什么大问题,但对于大型内存缓冲区,这可能是一个昂贵的操作。 (例如,参见Archive::Libarchive,您可以使用tar文件传入Buf。该代码是否有问题?

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

有没有(可能有吗?应该有吗?)trait上的某种Buf告诉GC不要移动它?我知道如果我向Buf添加更多数据可能会有麻烦,但我保证不这样做。对于一个不可变的Blob怎么样?

perl6
1个回答
6
投票

你可以在MoarVM上使用它,至少在目前,只要你在本机代码需要的时候保持对perl 6中的BlobBuf的引用,并且(在Buf的情况下)你不要写一个可能导致调整大小的写入。

MoarVM在托儿所内部分配Blob / Buf对象,并在GC运行期间移动它。但是,该对象不包含数据;相反,它保持大小和指向保存值的内存块的指针。该内存块未使用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标记为这样。也许更好的方法是I / O-ish要求提供类似CArray的东西,以便通过将数据放在“正确类型的存储器”中来实现零拷贝。这可能是一个合理的功能请求。

© www.soinside.com 2019 - 2024. All rights reserved.