之前买的张丹的R极客理想的这本书想起来有R性能监控这部分的内容,学习了下。
1、Rprof
首先是R自带的Rprof包,不需要安装,直接导入即可
tmp = "tRprof.out"
Rprof(tmp, line.profiling= TRUE, memory.profiling=TRUE)
<R代码>
Rprof(NULL)
# 最后会生成一个tRprof.out文件,可以在R里面导入读取
summaryRprof("tRprof.out")
- by.self: 这部分显示了每个函数自身执行所消耗的时间,不包括它调用的其他函数的时间。
- by.total: 这部分显示了包括调用其他函数在内的每个函数的总时间消耗。
- self.time: 函数自身执行的平均时间。
- total.time: 函数包括调用其他函数在内的平均总时间。
- percent.self: 每个函数自身时间消耗占总时间的百分比。
- percent.of.total: 每个函数总时间消耗占总时间的百分比。
2、profvis(旧的是lineprof)
安装:
conda install -c conda-forge pandoc # 如果没有的话需要安装
R
install.packages("profvis")
使用:
library(profvis)
profvis({
# 你的代码块
})
这个更容易看资源消耗的情况,结果可以输出来一个html,示例:
library(profvis)
p<- profvis({
my_cumsum2<- function(x){
y<- numeric(length(x))
y[[1]]<- x[[1]]
for(i in 2:length(x)){
y[[i]]<- y[[i-1]]+ x[[i]]
}
y
}
x<- rnorm(1000)
for(i in 1:1000){
my_cumsum2(x)
}
})
htmlwidgets::saveWidget(p, "profile.html")
- 时间(Time):profvis中的时间单位通常是毫秒(ms)。这意味着,如果你看到某个函数或代码块的时间是100,那么它表示该函数或代码块执行了100毫秒。
- 内存(Memory):profvis中的内存单位通常是字节(bytes)。R语言中内存的使用量通常以字节为单位来表示,这可以帮助你了解代码在执行过程中的内存消耗情况。
但是发现对于复杂的脚本,以及消耗内存比较大的程序会跑的很慢很慢很慢,于是放弃了。
3、pidstat
最后选的是这个工具来对复杂脚本的消耗内存比较大的步骤进行了优化。
这个其实是linux监控程序运行的一个命令,只会输出系统时间间隔下的内存消耗情况。因此如果在R脚本中配合使用的话需要在代码中输出时间戳,可以在每个关键步骤的代码前后输出系统时间。最终就可以根据pidstat的输出日志,找到内存消耗最大的步骤了。
比如,R代码中:
print(paste0("----------- FindNeighbors Start: ", date()))
#Cluster the cells
combined <- FindNeighbors(object = combined, reduction = "integrated.cca", dims = 1:dim)
print(paste0("----------- FindNeighbors Start: ", date()))
在FindNeighbors
这行代码的开始和结束加上一个print, date()
输出的就是系统时间。
任务投递之后会有一个pid,可以通过top查看。确定了pid后,立马运行如下命令:
# 这里示例的pid是129354
nohup pidstat -r -p 129354 10 > log &
参数含义
pidstat -r -p 270967 5
● pidstat: 是系统监控工具,属于sysstat包。
● -r: 报告内存使用情况
● -p 129354: 指定监控的进程ID(PID)为270967。
● 10: 每隔10秒刷新显示一次数据。
结果含义:
● 09时43分16秒: 显示数据的时间戳。
● UID: 运行进程的用户ID。
● PID: 进程ID。
● minflt/s: 每秒发生的次数,minor page faults不会引起磁盘I/O。
● majflt/s: 每秒发生的次数,major page faults会涉及磁盘I/O。
● VSZ: Virtual Set Size,虚拟内存大小,进程使用的虚拟内存总量。
● RSS: Resident Set Size,常驻内存大小,进程实际占用的物理内存量。
● %MEM: 进程占用的内存百分比。
● Command: 进程的命令名称。