Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help find and troubleshoot pprof installation #15

Merged
merged 9 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Generated by roxygen2: do not edit by hand

export(assert_pprof)
export(pprof)
export(pprof_path)
export(record_pprof)
export(record_rprof)
export(serve_pprof)
export(serve_rprof)
export(test_pprof)
export(to_pprof)
export(to_rprof)
importFrom(RProtoBuf,readProtoFiles)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* In the `DESCRIPTION`, unquote function names and add parentheses afterwards. (CRAN comments for next submission.)
* Motivate profilers more in the README.
* Increase font size in logo.
* Search systems for `pprof` if the `pprof_path` env var is not set (#14, @krlmlr).
* Export `assert_pprof()` (#13, @krlmlr).

# proffer 0.0.2

Expand Down
36 changes: 6 additions & 30 deletions R/pprof.R
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ serve_rprof <- function(
#' Chosen randomly by default.
#' @param browse Logical, whether to open a browser to view
#' the pprof server.
#' @param verbose Logical, whether to print the URL of the pprof
#' server to the R console as a message.
#' @param verbose Logical, whether to print console messages
#' such as the URL of the local `pprof` server.
#' @examples
#' \dontrun{
#' pprof <- record_pprof(replicate(1e2, sample.int(1e4)))
Expand All @@ -104,11 +104,11 @@ serve_pprof <- function(
browse = interactive(),
verbose = TRUE
) {
assert_pprof()
assert_pprof(verbose)
server <- sprintf("%s:%s", host, port %||% random_port())
url <- sprintf("http://%s", server)
args <- c("-http", server, pprof)
px <- serve_pprof_impl(args)
px <- serve_pprof_impl(args, verbose)
if (verbose) {
message(url)
}
Expand All @@ -118,36 +118,12 @@ serve_pprof <- function(
px
}

serve_pprof_impl <- function(args) {
serve_pprof_impl <- function(args, verbose) {
processx::process$new(
command = get_pprof_path(),
command = pprof_path(verbose),
args = args,
stdout = "|",
stderr = "|",
supervise = TRUE
)
}

random_port <- function(from = 49152L, to = 65355L) {
sample(seq.int(from = from, to = to, by = 1L), size = 1L)
}

assert_pprof <- function() {
if (file.exists(get_pprof_path())) {
return()
}
missing_pprof()
}

missing_pprof <- function() {
stop(
"cannot find pprof at ",
shQuote(get_pprof_path()),
". See the setup instructions at https://r-prof.github.io/proffer.",
call. = FALSE
)
}

get_pprof_path <- function() {
Sys.getenv("pprof_path")
}
103 changes: 103 additions & 0 deletions R/troubleshoot.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#' @title Test `pprof()`
#' @export
#' @seealso [pprof()]
#' @description Do a test run of `pprof()` to verify that the
#' system dependencies like `pprof` work as expected.
#' @details See <https://github.com/r-prof/proffer#installation>
#' for setup instructions.
#' @inheritParams pprof
#' @examples
#' \dontrun{
#' test_pprof()
#' }
test_pprof <- function(
host = "localhost",
port = NULL,
browse = interactive(),
verbose = TRUE
) {
slow_function <- function() {
n <- 1e3
x <- data.frame(x = sample.int(n), y = sample.int(n))
for (i in seq_len(n)) {
x[i, ] <- x[i, ] + 1
}
x
}
pprof(
slow_function(),
host = host,
port = port,
browse = browse,
verbose = verbose
)
}

#' @title Check if `proffer` can find your `pprof` installation.
#' @export
#' @description Returns silently if `pprof` is installed
#' and throws an error if `pprof` is missing.
#' @details See <https://github.com/r-prof/proffer#installation>
#' for setup instructions.
#' @param verbose Logical, whether to print out messages
#' when `proffer` is having trouble searching for `pprof`.
#' @examples
#' \dontrun{
#' assert_pprof()
#' }
assert_pprof <- function(verbose = TRUE) {
if (file.exists(pprof_path(verbose = verbose))) {
return(invisible())
}
missing_pprof()
}

missing_pprof <- function() {
stop(
"cannot find pprof executable. ",
"See the setup instructions at https://r-prof.github.io/proffer.",
call. = FALSE
)
}

#' @title Show the path to the pprof executable.
#' @export
#' @description Defaults to the `pprof_path` environment variable.
#' Otherwise, it searches your Go lang installation for `pprof`.
#' @details See <https://github.com/r-prof/proffer#installation>
#' for setup instructions.
#' @return Character, path to `pprof` it exists and `""` otherwise.
#' @param verbose Logical, whether to print out messages
#' when `proffer` is having trouble searching for `pprof`.
#' @examples
#' \dontrun{
#' pprof_path()
#' }
pprof_path <- function(verbose = TRUE) {
pprof_path <- Sys.getenv("pprof_path")
if (file.exists(pprof_path)) {
return(pprof_path)
}
pprof_search(verbose)
}

pprof_search <- function(verbose) {
if (nchar(Sys.which("go")) == 0) {
verbose_msg(verbose, "Go lang compiler tools not installed.")
return("")
}
gopath <- system2("go", c("env", "GOPATH"), stdout = TRUE)
if (!dir.exists(gopath)) {
verbose_msg(verbose, "Cannot find 'GOPATH' at", gopath)
return("")
}
pprof_path <- file.path(gopath, "bin", "pprof")
if (.Platform$OS.type == "windows") {
pprof_path <- paste0(pprof_path, ".exe")
}
if (!file.exists(pprof_path)) {
verbose_msg(verbose, "Cannot find pprof in GOPATH: ", pprof_path)
return("")
}
pprof_path
}
11 changes: 11 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@
x
}
}

random_port <- function(from = 49152L, to = 65355L) {
sample(seq.int(from = from, to = to, by = 1L), size = 1L)
}

verbose_msg <- function(verbose, ...) {
stopifnot(is.logical(verbose))
if (verbose) {
message(paste(...))
}
}
19 changes: 14 additions & 5 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,22 @@ px$is_alive()
px$read_error() # Why did it quit soon?
#> [1] "sh: /user/local/bin/pprof: No such file or directory\nWarning message:\nIn system2(Sys.getenv(\"pprof_path\"), args) : error in running command\n"

# Oh, I must have set the wrong path to the pprof executable.
# Can my system find pprof?
test_pprof()
#> Error: cannot find pprof executable. See the setup instructions at https://r-prof.github.io/proffer.
assert_pprof()
#> Error: cannot find pprof executable. See the setup instructions at https://r-prof.github.io/proffer.
pprof_path()
#> ""

# Maybe my system cannot find the pprof executable.
# Let me find out where I actually installed pprof.
system("which", "pprof")
#> "/home/landau/go/bin/pprof"
#> "/home/landau/alternative/path/pprof"

# I can put a line in my .Rprofile or .Renviron file
# to automatically tell new sessions where pprof lives.
Sys.setenv(pprof_path = "/home/landau/go/bin/pprof")
Sys.setenv(pprof_path = "/home/landau/alternative/path/pprof")

# Now, pprof should work.
px <- pprof({
Expand Down Expand Up @@ -156,9 +164,10 @@ Alternatively, you can install the development version from GitHub.
remotes::install_github("r-prof/proffer")
```

To use functions `pprof()` and `serve_pprof()`, you need to install [`pprof`](https://github.com/google/pprof). Installing `pprof` is hard, so if you have trouble, please do not hesitate to [open an issue](https://github.com/r-prof/proffer/issues) and ask for help. And if you cannot install `pprof`, then [`profvis`](https://rstudio.github.io/profvis/) is an excellent alternative.
To use functions `pprof()` and `serve_pprof()`, [`pprof`](https://github.com/google/pprof) needs to be installed. This requires a working Go installation and Graphviz. If you have trouble, please do not hesitate to [open an issue](https://github.com/r-prof/proffer/issues) and ask for help. The [`profvis`](https://rstudio.github.io/profvis/) package is an excellent alternative with fewer dependencies.

As you follow the installation instructions below, you can run `test_pprof()`, `assert_pprof()`, or `pprof_path()` at any time to see if `proffer` can find and use `pprof`. If these functions succeed early, you are already done.

1. Install the [`RProtoBuf`](https://github.com/eddelbuettel/rprotobuf) package. On Linux, you also need to install the supporting protocol buffer libraries, e.g. `sudo apt-get install protobuf-compiler libprotobuf-dev libprotoc-dev` on Ubuntu.
1. Install [Graphviz](https://www.graphviz.org) and ensure the Graphviz executables appear in your `PATH` environment variable ([directions here](https://bobswift.atlassian.net/wiki/spaces/GVIZ/pages/131924165/Graphviz+installation)).
1. [Install the Go programming language](https://golang.org/doc/install).
1. Ensure your system can find the Go binaries. Open your command line interface of choice (e.g. Terminal or Command Prompt) and type `go version`. If you get an error, you may need to set the `PATH` environment variable as described [here for Linux](https://www.callicoder.com/golang-installation-setup-gopath-workspace/#linux) and [here for Windows](http://www.wadewegner.com/2014/12/easy-go-programming-setup-for-windows/)
Expand Down
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ system.time({
x <- data.frame(x = x, y = y)
})
#> user system elapsed
#> 0.050 0.003 0.054
#> 0.046 0.001 0.048
```

Moral of the story: before you optimize, throw away your assumptions and
Expand Down Expand Up @@ -108,14 +108,22 @@ px$is_alive()
px$read_error() # Why did it quit soon?
#> [1] "sh: /user/local/bin/pprof: No such file or directory\nWarning message:\nIn system2(Sys.getenv(\"pprof_path\"), args) : error in running command\n"

# Oh, I must have set the wrong path to the pprof executable.
# Can my system find pprof?
test_pprof()
#> Error: cannot find pprof executable. See the setup instructions at https://r-prof.github.io/proffer.
assert_pprof()
#> Error: cannot find pprof executable. See the setup instructions at https://r-prof.github.io/proffer.
pprof_path()
#> ""

# Maybe my system cannot find the pprof executable.
# Let me find out where I actually installed pprof.
system("which", "pprof")
#> "/home/landau/go/bin/pprof"
#> "/home/landau/alternative/path/pprof"

# I can put a line in my .Rprofile or .Renviron file
# to automatically tell new sessions where pprof lives.
Sys.setenv(pprof_path = "/home/landau/go/bin/pprof")
Sys.setenv(pprof_path = "/home/landau/alternative/path/pprof")

# Now, pprof should work.
px <- pprof({
Expand Down Expand Up @@ -164,14 +172,19 @@ Alternatively, you can install the development version from GitHub.
remotes::install_github("r-prof/proffer")
```

To use functions `pprof()` and `serve_pprof()`, you need to install
[`pprof`](https://github.com/google/pprof). Installing `pprof` is hard,
so if you have trouble, please do not hesitate to [open an
issue](https://github.com/r-prof/proffer/issues) and ask for help. And
if you cannot install `pprof`, then
To use functions `pprof()` and `serve_pprof()`,
[`pprof`](https://github.com/google/pprof) needs to be installed.
Installing `pprof` is hard, so if you have trouble, please do not
hesitate to [open an issue](https://github.com/r-prof/proffer/issues)
and ask for help. And if you cannot install `pprof`, then
[`profvis`](https://rstudio.github.io/profvis/) is an excellent
alternative.

As you follow the installation instructions below, you can run
`test_pprof()`, `assert_pprof()`, or `pprof_path()` at any time to see
if `proffer` can find and use `pprof`. If these functions succeed early,
you are already done.

1. Install the [`RProtoBuf`](https://github.com/eddelbuettel/rprotobuf)
package. On Linux, you also need to install the supporting protocol
buffer libraries, e.g. `sudo apt-get install protobuf-compiler
Expand Down
5 changes: 5 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ reference:
contents:
- '`to_pprof`'
- '`to_rprof`'
- title: Troubleshoot
contents:
- '`test_pprof`'
- '`assert_pprof`'
- '`pprof_path`'
11 changes: 11 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
AppVeyor
Codecov
cran
datatable
env
environ
github
Graphviz
http
https
io
lang
nz
pprof
Pprof
processx
profiler
profilers
profvis
README
Rprof
stonger
usethis
wlandau
www
25 changes: 25 additions & 0 deletions man/assert_pprof.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/pprof.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading