我正在使用 future Promise 与管道工包中的 API 进行交互。为了避免 RAM 积累,我使用了 callr plan(查看this post 了解更多详情),但它会在每个 API 的计算中产生延迟(将某些 API 从 0.1 秒缩短到 3 秒,这会严重影响性能),我正在寻找减少这种延迟的方法。
当我从下面的 reprex 运行 API1 时,多会话计划需要 0.2 秒,调用者需要 3.1 秒。在这两种情况下,计算 Promise 的时间都非常短(0.01 秒,通过 API 内的 Sys.time 进行测量)。因此我得出的结论是延迟来自于承诺准备。
延迟似乎与承诺中使用的 R 包有关。我比较了3个API:API1使用之前加载的terra包。 API2 使用带有
terra::rast
的 terra 包。 API3不使用terra,但有一个Sys.sleep()
对应于我正在使用的terra函数的计算时间。 API1 和 API2 都需要 3 秒来计算,但承诺时间有所不同(API1 在 0.01 秒内计算出承诺,API2 需要 2.4 秒)。 API3 速度更快,计算时间为 0.7 秒(包括承诺的 0.03 秒)。因此,延迟似乎来自于处理包(我有类似 sf 包的东西),并且之前加载包(library(terra)
)或调用它们进行特定用途(terra::rast()
)并没有什么区别。有没有办法减少这种延迟?
以下是代表:
调用 API 的脚本(您可以选择注释 L3 或 L4 以使用多会话或调用者进行测试):
### Set the asynchronous coding
library(promises) ; library(future) ; library(future.callr)
#future::plan("multisession")
future::plan(future.callr::callr)
### Plumber app
library(plumber)
### Other libraries
library(terra)
### Measure time to compute the terra function
T1_delay=Sys.time() ; terra_delay=terra::rast(xmin=-10, xmax=10, ymin=-10, ymax=10, resolution=10, crs="+init=epsg:4326") ; Delay=Sys.time()-T1_delay
### Start app
pr <- pr("Test_callr_APIs.R")
pr %>% pr_run()
保存在“Test_callr_APIs.R”中的代码:
#* API1
#* @get species/<scientific_name>/API1
#* @param scientific_name:string Scientific Name
#* @serializer unboxedJSON
#* @tag test
function(scientific_name) {
Prom<-future({
T1<-Sys.time()
raster_test<-rast(xmin=-10, xmax=10, ymin=-10, ymax=10, resolution=10, crs="+init=epsg:4326")
cat(Sys.time()-T1, "\n")
return(list(object_to_return=2))
}, gc=T, seed=T)
return(Prom)
}
#* API2
#* @get species/<scientific_name>/API2
#* @param scientific_name:string Scientific Name
#* @serializer unboxedJSON
#* @tag test
function(scientific_name) {
Prom<-future({
T1<-Sys.time()
raster_test<-terra::rast(xmin=-10, xmax=10, ymin=-10, ymax=10, resolution=10, crs="+init=epsg:4326")
cat(Sys.time()-T1, "\n")
return(list(object_to_return=2))
}, gc=T, seed=T)
return(Prom)
}
#* API3
#* @get species/<scientific_name>/API3
#* @param scientific_name:string Scientific Name
#* @serializer unboxedJSON
#* @tag test
function(scientific_name) {
Prom<-future({
T1<-Sys.time()
Sys.sleep(Delay)
cat(Sys.time()-T1, "\n")
return(list(object_to_return=2))
}, gc=T, seed=T)
return(Prom)
}
您观察到的延迟增加来自于
future.callr::callr
每次启动新的 R 进程(使用 callr::r_bg()
)以及在该新进程中加载所有必需的包。这需要时间,而且没有太多可做的。我唯一能想象的就是看看callr::r_bg()
是否可以变得更快(我对此表示怀疑)以及R和Rscript
本身的启动过程(R-devel邮件列表的东西)。