suppressMessages(library(strucchange)) suppressMessages(library(bfast)) suppressMessages(if (!require(igraph)) stop("this report uses the igraph package, please install it with install.packages(\"igraph\")")) buildProfileGraph <- function(profobj, threshold = 2.5) { invisible(require(igraph)) edges = data.frame(from=NULL,to=NULL,weight=NULL) vertices = data.frame(name=NULL,label=NULL,weight=NULL) for (i in 1:length(profobj$time)) { for (j in 1:nrow(profobj$ref[[i]])) { # if vertex with name profobj$ref[[i]]$f[i] does not exist, create it vname = paste(profobj$ref[[i]]$f[1:j],collapse="/") vs = which(vertices$name == vname) if (length(vs)==0) { vertices = rbind(vertices,data.frame(name=vname, label=profobj$ref[[i]]$f[j], weight=profobj$time[i], stringsAsFactors = FALSE)) } else if (length(vs)==1) { vertices$weight[vs] = vertices$weight[vs] + profobj$time[i] } else { warning("duplicate vertices") next } } if (nrow(profobj$ref[[i]]) > 1) { for (j in 1:(nrow(profobj$ref[[i]])-1)) { vname0 = paste(profobj$ref[[i]]$f[1:j],collapse="/") vname1 = paste(profobj$ref[[i]]$f[1:(j+1)],collapse="/") es = which(edges$from ==vname0 & edges$to == vname1) # if edge from profobj$ref[[i]]$f[j] to profobj$ref[[i]]$f[j+1] does not exist, create it if (length(es) == 0) { edges = rbind(edges,data.frame(from=vname0, to=vname1, weight=profobj$time[i]),stringsAsFactors=FALSE) # TODO: add weight } else if (length(es) == 1) { # add weight profobj$time[i]... edges$weight[es] =edges$weight[es] + profobj$time[i] # TODO: add proper weight } else { warning("duplicate edges") next } } } } vertices$reltime =round(100*vertices$weight / sum(profobj$time),digits = 1) vertices =vertices[which(vertices$reltime >= threshold),] edges = edges[which(edges$from %in% vertices$name & edges$to %in% vertices$name),] df.g <- graph.data.frame(d = edges, directed = T,vertices = vertices) V(df.g)$label = paste(V(df.g)$label,"\n", V(df.g)$reltime , "%", sep="") return(df.g) }
This document identifies computational bottlenecks in functions from benchmark.R
.
Below, two tables for all test functions present profiling results with set_default_options()
and set_fast_options()
respectively.
suppressMessages(if (!require(lineprof)) stop("this report uses the igraph package, please install it with install.packages(\"lineprof\")")) suppressMessages(library(knitr)) test.env = new.env() source("benchmark.R", local = test.env ) # find all functions in environment fs = names(which(sapply(ls(test.env), function(x) {return(class(get(x, envir = test.env)))}) == "function")) results.default = list() results_prof.default = list() results.fast= list() results_prof.fast = list() ftest = c("model.frame","cumsum","computeEmpProc","extend.RSS.table","RSS","RSSi","extract.breaks", "computeEstims","root.matrix", "crossprod", "border","model.response","model.matrix","outer","as.character","factor","as.ts","ts","%*%","as.vector","as.matrix","lm","lm.fit", unique(c(ls(envir = environment(bfast::bfast)), ls(envir = environment(strucchange::monitor))))) for (i in 1:length(fs)) { cat(paste("Running ", fs[i], "() ...\n", sep="")) f = get(fs[i],envir = test.env) set_default_options() lprof = lineprof(f(),interval = 0.005) results_prof.default[[fs[i]]] = lprof res = data.frame(f=ftest, time=rep(NA,length(ftest))) res$time = sapply(ftest,function(y) { sum(focus(lprof, y)$time)},simplify = "array") res = res[order(res$time,decreasing = T),] res = res[which(res$time > 0),] res = rbind(data.frame(f="(TOTAL)",time=sum(lprof$time)), res) res$rel_time = res$time / res$time[1] results.default[[fs[i]]] = res set_fast_options() lprof = lineprof(f(),interval = 0.005) results_prof.fast[[fs[i]]] = lprof res = data.frame(f=ftest, time=rep(NA,length(ftest))) res$time = sapply(ftest,function(y) { sum(focus(lprof, y)$time)},simplify = "array") res = res[order(res$time,decreasing = T),] res = res[which(res$time > 0),] res = rbind(data.frame(f="(TOTAL)",time=sum(lprof$time)), res) res$rel_time = res$time / res$time[1] results.fast[[fs[i]]] = res }
for (fname in names(results.default)) { # print bottlenecks old vs new, show only functions with more than or equal to 2% of the total computation times cat(paste("### Function:",fname)) cat("\n") rownames(results.default[[fname]]) <- NULL rownames(results.fast[[fname]]) <- NULL print(kable(results.default[[fname]][which(results.default[[fname]]$rel_time >= 0.02),],format="markdown")) cat("\n") print(kable(results.fast[[fname]][which(results.fast[[fname]]$rel_time >= 0.02),],format="markdown")) cat("\n") }
The following graphs present call graphs of most expensive operations. Given percentages represent the time a function needs to complete relative to the overall computation time. For all test functions, two graphs with set_default_options()
and set_fast_options()
respectively are shown.
for (fname in names(results_prof.default)) { par(mar=c(0,0,1,0)) graph = buildProfileGraph(results_prof.default[[fname]]) plot(graph,main=paste("Function: ", fname, " (orig.)", sep=""),layout=layout_(graph,as_tree()), vertex.size = 6,vertex.frame.color="gray", vertex.label.cex = 0.3,vertex.label.color="black", vertex.color="gray", edge.width=0.7, edge.arrow.width=0.0) graph = buildProfileGraph(results_prof.fast[[fname]]) plot(graph,main=paste("Function: ", fname, " (mod.)", sep=""),layout=layout_(graph,as_tree()), vertex.size = 6,vertex.frame.color="gray", vertex.label.cex = 0.3,vertex.label.color="black", vertex.color="gray", edge.width=0.7, edge.arrow.width=0.0) }
This report has been generated on r Sys.time()
.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.