-
Notifications
You must be signed in to change notification settings - Fork 142
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
Propose a faster version of check_installed()
#1776
Comments
I think we could assume that if the package is loaded, then it's installed. It might just be that |
If you load the package e.g. call
I don't see In light of the above, I think it'd safe to make the "if the package is loaded, then it's installed" assumption if only package names are supplied. |
Can you do a little exploration of |
This reported issue: #1561 is the reason it's checked if the package is installed on disk. Which seems quite improbable... But as a result, almost half the time is spent on this disk check and the other half on version comparison. I think the solution is a re-factoring of |
It was line 82 that I was thinking of; I agree that deleting a loaded package is a relatively esoteric case that we don't need to protect against. If we really believe that this case is worth thinking about then, we could also provide a faster implementation: bench::mark(
suppressWarnings(nzchar(system.file(package = "ggplot2"))),
file.exists(find.package("ggplot2")),
any(file.exists(file.path(.libPaths(), "ggplot2")))
)
#> # A tibble: 3 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 "file.exists(find.package(\"gg… 98.56µs 110.33µs 8721. 7.88KB 12.2
#> 2 "suppressWarnings(nzchar(syste… 100µs 108.49µs 8996. 2.08KB 14.3
#> 3 "any(file.exists(file.path(.li… 1.93µs 2.21µs 442941. 0B 0 Created on 2025-02-12 with reprex v2.1.0 |
Very nice. I also use (3) in mirai. Let's take this easy win - I'll open up a PR. I think there's still room for a refactor, but I want to make sure it won't break anything before I propose anything. |
Ah one of the main reasons for the rest of the slowness is the regex parsing to support for the 'pkg' argument:
Changing that would break existing behaviour. I expect it supports parsing the DESCRIPTION requirements. Hence I wonder if having another faster version would be a good idea, where the inputs are well-defined. |
I wonder if we could include a special case for simple package names? Or maybe we could return immediately if |
I like this idea.
I'm not sure I understand but it seems like bypassing the version check when the package is installed defeats the purpose of supplying a minimum version? |
I just meant that |
That's interesting. By the same measure, I'm going to put my shortcut proposal in a PR for review. This will prevent the full code path being run repeatedly within a session. |
This function provides a much better user experience for code using 'suggests' packages over some formulation of
if (requireNamespace("x", quietly = TRUE))
.However, it's much more expensive to use (a full 3 orders of magnitude):
Created on 2025-02-12 with reprex v2.1.1
In purrr, I employ caching to ensure it's not run time every time a function is called e.g. https://github.com/tidyverse/purrr/blob/main/R/map.R#L214-L217 but I notice in other codebases it's often used unconditionally at the top of a function body (FYI @hadley).
Rather than require the user to implement these optimizations, it might be nice to handle this at source by short-cutting detection if the package is already loaded. This can be easily done using
.getNamespace()
, a really cheap function which returns either the namespace environment if already loaded or elseNULL
.Note that this would be different to current behaviour as
check_installed()
actually checks if the package is installed on disk (which contributes to the slowness). Hence a question is: do we hide this behind an argument, or would it be cleaner to introduce another function e.g.check_available()
?The text was updated successfully, but these errors were encountered: