• Posts tagged "Rprof"

Blog Archives

R语言性能可视化lineprof

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-perform-lineprof/

lineprof-r

前言

数据可视化越来越受到人们的追捧,图形比文字更有表达力,基于HTML的可交互的图形比静态的PNG图片更让人惊喜。R语言已经为数据可视化做了充分的准备,简简单单地几行代码,就可以让数据变成图片,让图片变成会动的图片。

本文以“性能报告”为切入点,讲述R语言可视化程序lineprof。

目录

  1. lineprof介绍
  2. lineprof安装
  3. lineprof使用
  4. lineprof的API介绍

1. lineprof介绍

lineprof是一个数据可视化的项目,为了更友好地可视化性能监控效果。上文中通过profr库,可以把性能数据以图片的形式输出,但缺点是仅仅是一张静态图片。而lineprof可以做的更好,生成基于shiny的可交互的网页,让你自己动手发现问题。

lineprof项目,又是“Hadley Wickham”大神的作品。目前项目只在github上面发布。github项目地址:https://github.com/hadley/lineprof

2. lineprof安装

系统环境

  • Linux: Ubuntu Server 12.04.2 LTS 64bit
  • R: 3.0.1 x86_64-pc-linux-gnu
  • RStudio Server online

由于项目lineprof,还没有发布到CRAN,仅支持github安装。我们要通过devtools来通过github来安装。

安装devtools工具


~ R
> install.packages("devtools")

devtools的详细安装说明和使用,请参考文章:在巨人的肩膀前行 催化R包开发

安装lineprof


> library(devtools)

> install_github("lineprof")
Installing github repo(s) lineprof/master from hadley
Downloading lineprof.zip from https://github.com/hadley/lineprof/archive/master.zip
Installing package from /tmp/RtmpnLt4fi/lineprof.zip
Installing lineprof
Installing dependencies for lineprof:
Rcpp
Installing package into ‘/home/conan/R/x86_64-pc-linux-gnu-library/3.0’
(as ‘lib’ is unspecified)
trying URL 'http://cran.rstudio.com/src/contrib/Rcpp_0.10.6.tar.gz'
Content type 'application/x-gzip' length 1985569 bytes (1.9 Mb)
opened URL
==================================================
downloaded 1.9 Mb

* installing *source* package ‘Rcpp’ ...
** package ‘Rcpp’ successfully unpacked and MD5 sums checked
** libs
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c Date.cpp -o Date.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c Module.cpp -o Module.o
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c Rcpp_init.c -o Rcpp_init.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c Timer.cpp -o Timer.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c api.cpp -o api.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c attributes.cpp -o attributes.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c barrier.cpp -o barrier.o
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include/     -fpic  -O3 -pipe  -g  -c exceptions.cpp -o exceptions.o
g++ -shared -o Rcpp.so Date.o Module.o Rcpp_init.o Timer.o api.o attributes.o barrier.o exceptions.o -L/usr/lib/R/lib -lR
g++ -o libRcpp.so Date.o Module.o Rcpp_init.o Timer.o api.o attributes.o barrier.o exceptions.o -shared   -L/usr/lib/R/lib -lR
ar qc libRcpp.a Date.o Module.o Rcpp_init.o Timer.o api.o attributes.o barrier.o exceptions.o
cp libRcpp.so ../inst/lib
cp libRcpp.a ../inst/lib
rm libRcpp.so libRcpp.a
installing to /home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/libs
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
* DONE (Rcpp)

The downloaded source packages are in
	‘/tmp/RtmpnLt4fi/downloaded_packages’
'/usr/lib/R/bin/R' --vanilla CMD INSTALL '/tmp/RtmpnLt4fi/lineprof-master'  \
  --library='/home/conan/R/x86_64-pc-linux-gnu-library/3.0'  \
  --with-keep.source --install-tests 

* installing *source* package 'lineprof' ...
** libs
g++ -I/usr/share/R/include -DNDEBUG   -I"/home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include"   -fpic  -O3 -pipe  -g  -c RcppExports.cpp -o RcppExports.o
g++ -I/usr/share/R/include -DNDEBUG   -I"/home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include"   -fpic  -O3 -pipe  -g  -c contains.cpp -o contains.o
g++ -I/usr/share/R/include -DNDEBUG   -I"/home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include"   -fpic  -O3 -pipe  -g  -c parse-refs.cpp -o parse-refs.o
g++ -shared -o lineprof.so RcppExports.o contains.o parse-refs.o -L/home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/lib -lRcpp -Wl,-rpath,/home/conan/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/lib -L/usr/lib/R/lib -lR
installing to /home/conan/R/x86_64-pc-linux-gnu-library/3.0/lineprof/libs
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (lineprof)

安装shiny控制台


> install_github("shiny-slickgrid", "wch")

加载lineprof

> library(lineprof)

3. lineprof使用

官文例子


> library(lineprof)
> source(find_ex("read-delim.r"))
> wine <- find_ex("wine.csv")

> x <- lineprof(read_delim(wine, sep = ","), torture = TRUE)
Zooming to read-delim.r (99% of total time)

> x <- lineprof(read_delim(wine, sep = ","), torture = TRUE)
Zooming to read-delim.r (97% of total time)

用shiny展示


> library(shinySlickgrid)
> shine(x)
Loading required package: shiny
Shiny URLs starting with /lineprof will mapped to /home/conan/R/x86_64-pc-linux-gnu-library/3.0/lineprof/www
Shiny URLs starting with /slickgrid will mapped to /home/conan/R/x86_64-pc-linux-gnu-library/3.0/shinySlickgrid/slickgrid

Listening on port 6742

lineprof-shiny

6列表格字段的解释:

  • #: 行号
  • source code: 监控的目标函数源代码
  • t: (total)当前行执行的总时间(秒)
  • r: (released) 释放内存量
  • a: (allocated) 分配内存量
  • d: (duplicates)重复次数

对函数性能数据的解释:

  • #6,用于加载数据,总时间占用:0.309s,分配内存:0.064mb,方法重复次数:14次
  • #15,用于清除数据,总时间占用:0.179s,释放内存:0.065mb,方法重复次数:37次

对例子资源的介绍:

  • read-delim.r: 目标函数的脚本文件
  • wine.csv: 测试数据集
  • x: lineprof生成的数据报告

查看文件:read-delim.r


function(file, header = TRUE, sep = ",", stringsAsFactors = TRUE) {
  # Determine number of fields by reading first line
  first <- scan(file, what = character(1), nlines = 1, sep = sep, quiet = TRUE)
  p <- length(first)
    
  # Load all fields
  all <- scan(file, what = as.list(rep("character", p)), sep = sep, 
    skip = if (header) 1 else 0, quiet = TRUE)

  # Convert from strings to appropriate types
  all[] <- lapply(all, type.convert, as.is = !stringsAsFactors)
  
  # Set column names
  if (header) {
    names(all) <- first
    rm(first)
  } else {
    names(all) <- paste0("V", seq_along(all))
  }
    
  # Convert list into data frame
  class(all) <- "data.frame"
  attr(all, "row.names") <- c(NA_integer_, -length(all[[1]]))
    
  all
}

查看文件:wine.csv


> df<-read.csv(file=wine)

> object.size(df)
20440 bytes

> head(df)
  type alcohol malic  ash alcalinity magnesium phenols flavanoids nonflavanoids proanthocyanins color  hue dilution proline
1    A   14.23  1.71 2.43       15.6       127    2.80       3.06          0.28            2.29  5.64 1.04     3.92    1065
2    A   13.20  1.78 2.14       11.2       100    2.65       2.76          0.26            1.28  4.38 1.05     3.40    1050
3    A   13.16  2.36 2.67       18.6       101    2.80       3.24          0.30            2.81  5.68 1.03     3.17    1185
4    A   14.37  1.95 2.50       16.8       113    3.85       3.49          0.24            2.18  7.80 0.86     3.45    1480
5    A   13.24  2.59 2.87       21.0       118    2.80       2.69          0.39            1.82  4.32 1.04     2.93     735
6    A   14.20  1.76 2.45       15.2       112    3.27       3.39          0.34            1.97  6.75 1.05     2.85    1450

x对象: lineprof生成的数据报告


> x
Reducing depth to 2 (from 8)
Common path: 
    time alloc release dups      ref               src
1  0.002 0.001   0.000    0  #3 read_delim       
2  0.049 0.009   0.003   11  #3 read_delim/scan  
3  0.026 0.001   0.008    0  #4 read_delim       
4  0.379 0.072   0.006   14  #7 read_delim/scan  
5  0.003 0.000   0.000    0 #11 read_delim       
6  0.106 0.015   0.030    3 #11 read_delim/lapply
7  0.008 0.004   0.000    3 #11 read_delim       
8  0.210 0.028   0.077   36 #16 read_delim/rm    
9  0.004 0.001   0.000    1 #22 read_delim       
10 0.035 0.005   0.004    8 #23 read_delim/[[    
11 0.002 0.000   0.000    1 #23 read_delim/length
12 0.001 0.000   0.000    1 #23 read_delim/c     
13 0.006 0.004   0.000    1 #23 read_delim       
14 0.001 0.000   0.000    0 #23 read_delim/attr<-

4. lineprof的API介绍

通过namespace文件定义,我们找到lineprof库开放的API函数。

功能函数:使用者的API

  • focus: 设置显示高度zoom
  • auto_focus: 自动设置显示高度zoom
  • lineprof: 记录CPU和内存的占用
  • shine: 用shiny输出

内部函数:辅助功能函数的,使用者用不到的API

  • align: 源代码对齐
  • find_ex: 用于加载demo
  • line_profile: 格式化性能监控数据的输出(Rprof)
  • parse_prof: 格式化输出
  • reduce_depth: 设置输出的深度

通过lineprof可视化工具,我们生成的报告,更灵活,更直观,更好看,还有用户交互,甚至是网页版本的。
再和profr效果比较一下吧,R语言性能监控工具Rprof

R语言正在飞速地进步着,需要更多IT人的推动!!你还在等什么呢?

转载请注明出处:
http://blog.fens.me/r-perform-lineprof/

打赏作者

R语言性能监控工具Rprof

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-perform-rprof-profr/

rprof-r

前言

随着R语言使用越来越深入,R语言的计算性能问题越来越突显。如何能清楚地了解一个算法对CPU的耗时,将成为性能优化的关键因素。

R的基础库提供性能监控的函数Rprof。

目录

  1. Rprof介绍
  2. Rprof的函数定义
  3. Rprof程序使用1: 股票数据分析案例
  4. Rprof程序使用2: 数据下载案例
  5. 用profr可视化性能指标
  6. Rprof的命令行使用

1. Rprof函数介绍

Rprof函数,是R语言核心包自带的一个性能数据日志函数,可以打印出函数的调用关系和CPU耗时的数据。再通过summaryRprof函数,分析Rprof生成的日志数据,获得性能报告。再通过profr库的plot函数,对报告进行可视化。

2. Rprof的函数定义

系统环境

  • Win7 64bit
  • R: 3.0.1 x86_64-w64-mingw32/x64 b4bit

Rprof函数在基础包utils中定义,所以就不用安装,直接可以使用。

查看Rprof的函数定义。


~ R

> Rprof
function (filename = "Rprof.out", append = FALSE, interval = 0.02,
memory.profiling = FALSE, gc.profiling = FALSE, line.profiling = FALSE,
numfiles = 100L, bufsize = 10000L)
{
if (is.null(filename))
filename <- ""
invisible(.External(C_Rprof, filename, append, interval,
memory.profiling, gc.profiling, line.profiling, numfiles,
bufsize))
}
<bytecode: 0x000000000d8efda8>

Rprof函数,用来生成日志文件,通常我们指需要指定filename就可以了。

3. Rprof程序使用: 股票数据分析案例

取股票数据作为测试数据集,000000_0.txt文件:1.38 MB (1,452,409 字节)

关于数据的业务含义,请参考文章:用RHive从历史数据中提取逆回购信息


> bidpx1<-read.csv(file="000000_0.txt",header=FALSE)
> names(bidpx1)<-c("tradedate","tradetime","securityid","bidpx1","bidsize1","offerpx1","offersize1")
> bidpx1$securityid<-as.factor(bidpx1$securityid)

> head(bidpx1)
  tradedate tradetime securityid bidpx1 bidsize1 offerpx1 offersize1
1  20130724    145004     131810  2.620     6960    2.630      13000
2  20130724    145101     131810  2.860    13880    2.890       6270
3  20130724    145128     131810  2.850   327400    2.851       1500
4  20130724    145143     131810  2.603    44630    2.800      10650
5  20130724    144831     131810  2.890    11400    3.000      77990
6  20130724    145222     131810  2.600  1071370    2.601      35750

> object.size(bidpx1)
1299920 bytes

字段解释

  • tradedate: 交易日期
  • tradetime: 交易时间
  • securityid: 股票ID
  • bidpx1: 买一价
  • bidsize1: 买一量
  • offerpx1: 卖一价
  • offersize1: 卖一量

计算任务:以securityid分组,计算每小时的买一价的平均值和买一总交易量


> library(plyr)

> fun1<-function(){
  datehour<-paste(bidpx1$tradedate,substr(bidpx1$tradetime,1,2),sep="")
  df<-cbind(datehour,bidpx1[,3:5])
  ddply(bidpx1,.(securityid,datehour),summarize,price=mean(bidpx1),size=sum(bidsize1))
}

> head(fun1())
  securityid   datehour    price      size
1     131810 2013072210 3.445549 189670150
2     131810 2013072211 3.437179 131948670
3     131810 2013072212 3.421000       920
4     131810 2013072213 3.509442 299554430
5     131810 2013072214 3.578667 195130420
6     131810 2013072215 1.833000    718940

以system.time函数查看fun1运行时间


> system.time(fun1())
用户 系统 流逝 
0.08 0.00 0.07
 
> system.time(fun1())
用户 系统 流逝 
0.06 0.00 0.06 

用Rprof记录统计数据


> file<-"fun1_rprof.out"
> Rprof(file)
> fun1()
> Rprof(NULL)

查看生成的文件:fun1_rprof.out


~ vi fun1_rprof.out

sample.interval=20000
"substr" "paste" "fun1" 
"paste" "fun1" 
"structure" "splitter_d" "ddply" "fun1" 
".fun" "" ".Call" "loop_apply" "llply" "ldply" "ddply" "fun1" 
".fun" "" ".Call" "loop_apply" "llply" "ldply" "ddply" "fun1" 
".fun" "" ".Call" "loop_apply" "llply" "ldply" "ddply" "fun1" 
"[[" "rbind.fill" "list_to_dataframe" "ldply" "ddply" "fun1" 

查看统计报告


> summaryRprof(file)
$by.self
            self.time self.pct total.time total.pct
".fun"           0.06    42.86       0.06     42.86
"paste"          0.02    14.29       0.04     28.57
"[["             0.02    14.29       0.02     14.29
"structure"      0.02    14.29       0.02     14.29
"substr"         0.02    14.29       0.02     14.29

$by.total
                    total.time total.pct self.time self.pct
"fun1"                    0.14    100.00      0.00     0.00
"ddply"                   0.10     71.43      0.00     0.00
"ldply"                   0.08     57.14      0.00     0.00
".fun"                    0.06     42.86      0.06    42.86
".Call"                   0.06     42.86      0.00     0.00
""             0.06     42.86      0.00     0.00
"llply"                   0.06     42.86      0.00     0.00
"loop_apply"              0.06     42.86      0.00     0.00
"paste"                   0.04     28.57      0.02    14.29
"[["                      0.02     14.29      0.02    14.29
"structure"               0.02     14.29      0.02    14.29
"substr"                  0.02     14.29      0.02    14.29
"list_to_dataframe"       0.02     14.29      0.00     0.00
"rbind.fill"              0.02     14.29      0.00     0.00
"splitter_d"              0.02     14.29      0.00     0.00

$sample.interval
[1] 0.02

$sampling.time
[1] 0.14
  • $by.self:当前函数的耗时情况
  • $by.total:整体函数调用的耗时情况

时间主要花在paste:0.02, ddply:0.06。

4. Rprof程序使用: 数据下载案例


> install.packages("stockPortfolio")
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/stockPortfolio_1.2.zip'
Content type 'application/zip' length 114669 bytes (111 Kb)
opened URL
downloaded 111 Kb

package ‘stockPortfolio’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
	C:\Users\Administrator\AppData\Local\Temp\RtmporLw4l\downloaded_packages
> library(stockPortfolio)
> fileName <- "Rprof2.log"
> Rprof(fileName)
> gr <- getReturns(c("GOOG", "MSFT", "IBM"), freq="week")
> Rprof(NULL)
> summaryRprof(fileName)$by.total[1:8,]
                    total.time total.pct self.time self.pct
"getReturns"              6.76    100.00      0.00     0.00
"read.delim"              6.66     98.52      0.00     0.00
"read.table"              6.66     98.52      0.00     0.00
"scan"                    4.64     68.64      4.64    68.64
"file"                    2.02     29.88      2.02    29.88
"as.Date"                 0.08      1.18      0.02     0.30
"strptime"                0.06      0.89      0.06     0.89
"as.Date.character"       0.06      0.89      0.00     0.00

时间主要花在file:1.94, scan:2.62, read.table:2.02。

5. 用profr可视化性能指标

安装profr


> install.packages("profr")
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/profr_0.2.zip'
Content type 'application/zip' length 25813 bytes (25 Kb)
opened URL
downloaded 25 Kb

package ‘profr’ successfully unpacked and MD5 sums checked

> library(profr)

数据可视化:第一个例子


> file<-"fun1_rprof.out"
> plot(parse_rprof(file))
> ggplot(parse_rprof(file))

plot-rplof

ggplot-rprof

数据可视化:第二个例子


> fileName <- "Rprof2.log"
> plot(parse_rprof(fileName))
> ggplot(parse_rprof(fileName))

plot-rprof2

ggplot-rprof2

6. Rprof的命令行使用

Rprof的命令行方法,用来方便的查看日志文件。

1). 查看Rprof命令行帮助


~ D:\workspace\R\preforemence\Rprof>R CMD Rprof --help
Usage: R CMD Rprof [options] [file]

Post-process profiling information in file generated by Rprof().

Options:
  -h, --help       print short help message and exit
  -v, --version    print version info and exit
  --lines          print line information
  --total          print only by total
  --self           print only by self
  --linesonly      print only by line (implies --lines)
  --min%total=     minimum % to print for 'by total'
  --min%self=      minimum % to print for 'by self'

If 'file' is omitted 'Rprof.out' is used

Report bugs at bugs.r-project.org .

命令行解释

  • -h, –help: 打印帮助信息
  • -v, –version: 打印版本信息
  • –lines: 打印显示多行
  • –total: 只显示总数
  • –self: 只显示自己
  • –linesonly: 只显示单行(配合–lines使用)
  • –min%total=: 显示total的不低于X的百分比
  • –min%self=: 显示self的不低于X的百分比

2). Rprof命令行使用

显示完整的报告


~ D:\workspace\R\preforemence\Rprof>R CMD Rprof fun1_rprof.out

Each sample represents 0.02 seconds.
Total run time: 0.14 seconds.

Total seconds: time spent in function and callees.
Self seconds: time spent in function alone.

   %       total       %        self
 total    seconds     self    seconds    name
 100.0      0.14       0.0      0.00     "fun1"
  71.4      0.10       0.0      0.00     "ddply"
  57.1      0.08       0.0      0.00     "ldply"
  42.9      0.06      42.9      0.06     ".fun"
  42.9      0.06       0.0      0.00     ".Call"
  42.9      0.06       0.0      0.00     ""
  42.9      0.06       0.0      0.00     "llply"
  42.9      0.06       0.0      0.00     "loop_apply"
  28.6      0.04      14.3      0.02     "paste"
  14.3      0.02      14.3      0.02     "[["
  14.3      0.02      14.3      0.02     "structure"
  14.3      0.02      14.3      0.02     "substr"
  14.3      0.02       0.0      0.00     "list_to_dataframe"
  14.3      0.02       0.0      0.00     "rbind.fill"
  14.3      0.02       0.0      0.00     "splitter_d"


   %        self       %      total
  self    seconds    total   seconds    name
  42.9      0.06      42.9      0.06     ".fun"
  14.3      0.02      28.6      0.04     "paste"
  14.3      0.02      14.3      0.02     "[["
  14.3      0.02      14.3      0.02     "structure"
  14.3      0.02      14.3      0.02     "substr"

只显示total指标,占用时间不低于50%的部分。


~ D:\workspace\R\preforemence\Rprof>R CMD Rprof --total --min%total=50 fun1_rprof.out

Each sample represents 0.02 seconds.
Total run time: 0.14 seconds.

Total seconds: time spent in function and callees.
Self seconds: time spent in function alone.

   %       total       %        self
 total    seconds     self    seconds    name
 100.0      0.14       0.0      0.00     "fun1"
  71.4      0.10       0.0      0.00     "ddply"
  57.1      0.08       0.0      0.00     "ldply"

转载请注明出处:
http://blog.fens.me/r-perform-rprof-profr/

打赏作者