与在 RStudio 中使用 saveRDS 相关的计时问题
Timing issue related to using saveRDS in RStudio
在执行循环之前调用 saveRDS 会导致循环时序不一致。这仅在使用 RStudio 时很明显;当 运行 从命令行使用 Rscript 的相同脚本时,该问题不存在。这可能是 RStudio 中 I/O 刷新延迟的结果。
- 其他人是否注意到这种行为?
- 有没有办法在调用 saveRDS 后强制 I/O 刷新?
在 Ubuntu 18.04LTS 64 位上使用 RStudio 1.1.463、R 3.5.2。
我通过在代码执行之前调用 gc() 并使用 gcinfo 启用 gc 消息以确保没有触发 gc 来消除垃圾收集器这个问题。我还尝试用 cmpfun 预编译函数;这也无济于事。
以下代码可用于重现该问题。
loop.test <- function() {
t <- c()
t0 <- Sys.time()
for (i in 1:10) {
t <- c(t, Sys.time() - t0)
Sys.sleep(0.01)
}
dt <- round(1000 * diff(t), 1)
print(dt)
print(summary(dt))
}
saveRDS(1:10, 'garb.rds')
loop.test()
代码将产生以下输出(以毫秒为单位的循环时间):
[1] 10.1 10.1 10.2 10.2 275.4 10.2 10.1 10.2 10.2
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.10 10.10 10.20 39.63 10.20 275.40
请注意,大延迟不会总是出现在同一次迭代中。
删除代码中的 saveRDS 调用将始终产生一致的(接近 10 毫秒)循环时间。
运行 来自命令行的代码通过 Rscript 将在有和没有 saveRDS 行的情况下工作。
以下是 RStudio 人员的回复:
一种可能性:RStudio 在 R "idle" 期间做一些后台工作(即:当 R 调用 R_ProcessEvents 时),我认为项目文件索引就是其中之一。 RStudio 为这些任务注册文件监视器,因此创建文件可能会导致 RStudio 在幕后执行一些重新索引工作。
我确认将 saveRDS() 调用中的保存目录更改为项目目录之外可以解决计时问题。所以我认为这支持文件索引理论。 RStudio v1.2 预览版在较小程度上展示了这种行为,因此空闲处理实现中可能发生了一些变化,但我没有这方面的更多信息。 RStudio 人员打开了一个错误报告来解决这个问题,希望很快就能得到修复。
所以现在,一些解决方法是:
- 在调用 saveRDS() 以允许重新索引操作发生后,以足够的延迟调用 Sys.sleep()。
- 将 saveRDS() 指向当前项目目录之外的文件以防止重新索引。
在执行循环之前调用 saveRDS 会导致循环时序不一致。这仅在使用 RStudio 时很明显;当 运行 从命令行使用 Rscript 的相同脚本时,该问题不存在。这可能是 RStudio 中 I/O 刷新延迟的结果。
- 其他人是否注意到这种行为?
- 有没有办法在调用 saveRDS 后强制 I/O 刷新?
在 Ubuntu 18.04LTS 64 位上使用 RStudio 1.1.463、R 3.5.2。
我通过在代码执行之前调用 gc() 并使用 gcinfo 启用 gc 消息以确保没有触发 gc 来消除垃圾收集器这个问题。我还尝试用 cmpfun 预编译函数;这也无济于事。
以下代码可用于重现该问题。
loop.test <- function() {
t <- c()
t0 <- Sys.time()
for (i in 1:10) {
t <- c(t, Sys.time() - t0)
Sys.sleep(0.01)
}
dt <- round(1000 * diff(t), 1)
print(dt)
print(summary(dt))
}
saveRDS(1:10, 'garb.rds')
loop.test()
代码将产生以下输出(以毫秒为单位的循环时间):
[1] 10.1 10.1 10.2 10.2 275.4 10.2 10.1 10.2 10.2
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.10 10.10 10.20 39.63 10.20 275.40
请注意,大延迟不会总是出现在同一次迭代中。
删除代码中的 saveRDS 调用将始终产生一致的(接近 10 毫秒)循环时间。
运行 来自命令行的代码通过 Rscript 将在有和没有 saveRDS 行的情况下工作。
以下是 RStudio 人员的回复:
一种可能性:RStudio 在 R "idle" 期间做一些后台工作(即:当 R 调用 R_ProcessEvents 时),我认为项目文件索引就是其中之一。 RStudio 为这些任务注册文件监视器,因此创建文件可能会导致 RStudio 在幕后执行一些重新索引工作。
我确认将 saveRDS() 调用中的保存目录更改为项目目录之外可以解决计时问题。所以我认为这支持文件索引理论。 RStudio v1.2 预览版在较小程度上展示了这种行为,因此空闲处理实现中可能发生了一些变化,但我没有这方面的更多信息。 RStudio 人员打开了一个错误报告来解决这个问题,希望很快就能得到修复。
所以现在,一些解决方法是:
- 在调用 saveRDS() 以允许重新索引操作发生后,以足够的延迟调用 Sys.sleep()。
- 将 saveRDS() 指向当前项目目录之外的文件以防止重新索引。