R代碼性能監(jiān)控

之前買的張丹的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")
結(jié)果數(shù)據(jù)結(jié)構(gòu)
  1. by.self: 這部分顯示了每個(gè)函數(shù)自身執(zhí)行所消耗的時(shí)間,不包括它調(diào)用的其他函數(shù)的時(shí)間。
  2. by.total: 這部分顯示了包括調(diào)用其他函數(shù)在內(nèi)的每個(gè)函數(shù)的總時(shí)間消耗。
  3. self.time: 函數(shù)自身執(zhí)行的平均時(shí)間。
  4. total.time: 函數(shù)包括調(diào)用其他函數(shù)在內(nèi)的平均總時(shí)間。
  5. percent.self: 每個(gè)函數(shù)自身時(shí)間消耗占總時(shí)間的百分比。
  6. 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")
  1. 時(shí)間(Time):profvis中的時(shí)間單位通常是毫秒(ms)。這意味著,如果你看到某個(gè)函數(shù)或代碼塊的時(shí)間是100,那么它表示該函數(shù)或代碼塊執(zhí)行了100毫秒。
  2. 內(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ù)。

pidstat -r -p <pid>結(jié)果(log文件)

結(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)程的命令名稱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容