之前買的張丹的R極客理想的這本書想起來有R性能監(jiān)控這部分的內(nèi)容,學(xué)習(xí)了下。
1、Rprof
首先是R自帶的Rprof包,不需要安裝,直接導(dǎo)入即可
tmp = "tRprof.out"
Rprof(tmp, line.profiling= TRUE, memory.profiling=TRUE)
<R代碼>
Rprof(NULL)
# 最后會(huì)生成一個(gè)tRprof.out文件,可以在R里面導(dǎo)入讀取
summaryRprof("tRprof.out")

- by.self: 這部分顯示了每個(gè)函數(shù)自身執(zhí)行所消耗的時(shí)間,不包括它調(diào)用的其他函數(shù)的時(shí)間。
- by.total: 這部分顯示了包括調(diào)用其他函數(shù)在內(nèi)的每個(gè)函數(shù)的總時(shí)間消耗。
- self.time: 函數(shù)自身執(zhí)行的平均時(shí)間。
- total.time: 函數(shù)包括調(diào)用其他函數(shù)在內(nèi)的平均總時(shí)間。
- percent.self: 每個(gè)函數(shù)自身時(shí)間消耗占總時(shí)間的百分比。
- percent.of.total: 每個(gè)函數(shù)總時(shí)間消耗占總時(shí)間的百分比。
2、profvis(舊的是lineprof)
安裝:
conda install -c conda-forge pandoc # 如果沒有的話需要安裝
R
install.packages("profvis")
使用:
library(profvis)
profvis({
# 你的代碼塊
})
這個(gè)更容易看資源消耗的情況,結(jié)果可以輸出來一個(gè)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")

- 時(shí)間(Time):profvis中的時(shí)間單位通常是毫秒(ms)。這意味著,如果你看到某個(gè)函數(shù)或代碼塊的時(shí)間是100,那么它表示該函數(shù)或代碼塊執(zhí)行了100毫秒。
- 內(nèi)存(Memory):profvis中的內(nèi)存單位通常是字節(jié)(bytes)。R語言中內(nèi)存的使用量通常以字節(jié)為單位來表示,這可以幫助你了解代碼在執(zhí)行過程中的內(nèi)存消耗情況。
但是發(fā)現(xiàn)對(duì)于復(fù)雜的腳本,以及消耗內(nèi)存比較大的程序會(huì)跑的很慢很慢很慢,于是放棄了。
3、pidstat
最后選的是這個(gè)工具來對(duì)復(fù)雜腳本的消耗內(nèi)存比較大的步驟進(jìn)行了優(yōu)化。
這個(gè)其實(shí)是linux監(jiān)控程序運(yùn)行的一個(gè)命令,只會(huì)輸出系統(tǒng)時(shí)間間隔下的內(nèi)存消耗情況。因此如果在R腳本中配合使用的話需要在代碼中輸出時(shí)間戳,可以在每個(gè)關(guān)鍵步驟的代碼前后輸出系統(tǒng)時(shí)間。最終就可以根據(jù)pidstat的輸出日志,找到內(nèi)存消耗最大的步驟了。
比如,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這行代碼的開始和結(jié)束加上一個(gè)print, date()輸出的就是系統(tǒng)時(shí)間。
任務(wù)投遞之后會(huì)有一個(gè)pid,可以通過top查看。確定了pid后,立馬運(yùn)行如下命令:
# 這里示例的pid是129354
nohup pidstat -r -p 129354 10 > log &
參數(shù)含義
pidstat -r -p 270967 5
● pidstat: 是系統(tǒng)監(jiān)控工具,屬于sysstat包。
● -r: 報(bào)告內(nèi)存使用情況
● -p 129354: 指定監(jiān)控的進(jìn)程ID(PID)為270967。
● 10: 每隔10秒刷新顯示一次數(shù)據(jù)。

結(jié)果含義:
● 09時(shí)43分16秒: 顯示數(shù)據(jù)的時(shí)間戳。
● UID: 運(yùn)行進(jìn)程的用戶ID。
● PID: 進(jìn)程ID。
● minflt/s: 每秒發(fā)生的次數(shù),minor page faults不會(huì)引起磁盤I/O。
● majflt/s: 每秒發(fā)生的次數(shù),major page faults會(huì)涉及磁盤I/O。
● VSZ: Virtual Set Size,虛擬內(nèi)存大小,進(jìn)程使用的虛擬內(nèi)存總量。
● RSS: Resident Set Size,常駐內(nèi)存大小,進(jìn)程實(shí)際占用的物理內(nèi)存量。
● %MEM: 進(jìn)程占用的內(nèi)存百分比。
● Command: 進(jìn)程的命令名稱。