在R中测试缓冲区是否已被刷新

6
我有一些非常大的文件需要处理,我使用多种不同的I/O函数来访问它们。其中最常用的是bigmemory包。
在写入文件时,我已经吃过亏了,必须刷新输出缓冲区,否则数据是否保存就很难确定。然而,这可能会导致等待时间非常长,因为bigmemory需要做很多事情(数分钟)。我不知道为什么会发生这种情况-它并不总是发生,也不容易重现。
有没有办法在R中确定是否已经刷新了I/O缓冲区,特别是对于bigmemory?如果操作系统很重要,那么可以限制回答的范围。
如果可以将答案推广到除bigmemory之外的其他内存映射函数或I/O流,则更好,因为我有时会依赖其他函数。
如果没有好的解决方案来检查缓冲区是否已经被清空,是否存在可以假定缓冲区已经被清空的情况?即是否除了使用flush()外还有其他方法?
更新:我应该澄清一下,这些都是二进制连接。@RichieCotton指出isIncomplete(),尽管帮助文档只提到了文本连接。不清楚它是否可用于二进制连接。

不确定在 bigmemory 中是否可用,但 isIncomplete 对于常规连接是有效的。 - Richie Cotton
谢谢!关于连接的帮助信息非常有限,只提到isIncomplete适用于文本连接的输出。你在二进制连接方面有过成功的经验吗? - Iterator
2个回答

0
这更能证明 isIncomplete() 是否适用于二进制文件吗?
# R process 1
zz <- file("~/test", "wb")
writeBin(c(1:100000),con=zz)
close(zz)

# R process 2
zz2 <- file("~/test", "rb")
inpp <- readBin(con=zz2, integer(), 10000)
while(isIncomplete(con2)) {Sys.sleep(1); inpp <- c(inpp, readBin(zz2),integer(), 10000)}
close(zz2)

(修改自help(connections)文件。)


感谢您进行测试。然而,除非我理解错了,您的示例只在输入缓冲区的情况下使用它。我不太清楚它是否适用于输出缓冲区。我对输出缓冲不够熟悉,无法确定是否可以以同样的方式进行测试。我只是不愿意超出文档范围 - 如果其行为是随机的,而不是确定性的,那么我就有可能遇到一堆损坏的数据。我曾经走过那条路,所以我很谨慎。 :) - Iterator
经过进一步测试,我认为isIncomplete()不适用于bigmemory对象:似乎这些对象是某种指针,而不是连接。 :( - Iterator
感谢您的建议和示例。事实证明,在这种情况下,缓冲区是在 R 之外处理的。 - Iterator

0

我会提出自己的答案,但我欢迎任何更清晰的解释。

从我目前看到的情况来看,各种连接函数(例如fileopencloseflushisOpenisIncomplete等)都基于特定的连接类型,例如文件、管道、URL和其他一些东西。

相比之下,bigmemory有自己的连接类型,而bigmemory对象是一个S4对象,具有用于操作系统缓冲区的内存地址插槽。一旦放置在那里,操作系统就负责刷新这些缓冲区。由于这是操作系统的责任,因此获取“脏”缓冲区的信息需要与操作系统交互,而不是与R交互。

因此,对于bigmemory,答案是否定的,因为数据存储在内核缓冲区中,尽管对于通过STDIO处理的其他连接(即存储在“用户空间”中)可能是肯定的。

如果想要更深入地了解操作系统/内核方面的知识,请参考这个SO上的问题;我正在调查一些程序(不仅仅是R+bigmemory),它们产生了缓冲刷新的奇怪现象,而那个帖子帮助我对内核方面有了更清晰的认识。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接