Skip to content

Commit cd350bc

Browse files
More performance improvements:
Add internal getSysCalls() - create sysCalls() once per R session. Add with_assert() and option to prune it
1 parent 502686f commit cd350bc

File tree

4 files changed

+103
-64
lines changed

4 files changed

+103
-64
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: future
2-
Version: 1.34.0-9135
2+
Version: 1.34.0-9136
33
Title: Unified Parallel and Distributed Processing in R for Everyone
44
Imports:
55
digest,

R/backend_api-evalFuture.R

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,43 @@ attachPackages <- function(packages) {
3232
} ## attachPackages()
3333

3434

35+
tmpl_expr_local <- bquote_compile(base::local({
36+
.(expr)
37+
}))
38+
39+
40+
getSysCalls <- local({
41+
sysCalls_local <- NULL
42+
sysCalls_no_local <- NULL
43+
44+
function(local = TRUE) {
45+
if (local) {
46+
if (is.null(sysCalls_local)) {
47+
## WORKAROUND: This makes assumption about withCallingHandlers()
48+
## and local(). In case this changes, provide internal options to
49+
## adjust this. /HB 2018-12-28
50+
skip <- getOption("future.makeExpression.skip.local", c(12L, 3L))
51+
sysCalls_local <<- function(calls = sys.calls(), from = 1L) {
52+
calls[seq.int(from = from + skip[1L], to = length(calls) - skip[2L])]
53+
}
54+
}
55+
sysCalls_local
56+
} else {
57+
if (is.null(sysCalls_no_local)) {
58+
## WORKAROUND: This makes assumption about withCallingHandlers()
59+
## In case this changes, provide internal options to adjust this.
60+
## /HB 2018-12-28
61+
skip <<- getOption("future.makeExpression.skip", c(6L, 3L))
62+
sysCalls_no_local <<- function(calls = sys.calls(), from = 1L) {
63+
calls[seq.int(from = from + skip[1L], to = length(calls) - skip[2L])]
64+
}
65+
}
66+
sysCalls_no_local
67+
}
68+
}
69+
})
70+
71+
3572
evalFuture <- function(
3673
data = list(
3774
core = list(
@@ -74,39 +111,40 @@ evalFuture <- function(
74111
immediateConditionClasses <- capture$immediateConditionClasses
75112
immediateConditionHandlers <- capture$immediateConditionHandlers
76113

77-
if (!is.null(immediateConditionHandlers)) {
78-
stop_if_not(is.list(immediateConditionHandlers))
79-
if (length(immediateConditionHandlers) > 0) {
80-
stop_if_not(
81-
!is.null(names(immediateConditionHandlers)),
82-
all(vapply(immediateConditionHandlers, FUN = is.function, FUN.VALUE = FALSE))
83-
)
84-
}
85-
}
86-
87114
backendPackages <- context$backendPackages
88115
strategiesR <- context$strategiesR
89116
threads <- context$threads
90117
forwardOptions <- context$forwardOptions
91118
if (is.null(threads)) threads <- NA_integer_
92-
if (length(forwardOptions) > 0) {
93-
stop_if_not(!is.null(names(forwardOptions)))
94-
}
95119
## This will eventually always be TRUE
96120
local <- context$local
97121
if (is.null(local)) local <- TRUE
98122

99-
stop_if_not(
100-
length(local) == 1L && is.logical(local) && !is.na(local),
101-
length(stdout) == 1L && is.logical(stdout),
102-
length(split) == 1L && is.logical(split) && !is.na(split),
103-
is.null(conditionClasses) || (is.character(conditionClasses) && !anyNA(conditionClasses) && all(nzchar(conditionClasses))),
104-
is.character(immediateConditionClasses) && !anyNA(immediateConditionClasses) && all(nzchar(immediateConditionClasses)),
105-
is.null(seed) || is_lecyer_cmrg_seed(seed) || (is.logical(seed) && !is.na(seed) || !seed),
106-
is.character(backendPackages) && !anyNA(backendPackages) && all(nzchar(backendPackages)),
107-
length(threads) == 1L && is.integer(threads) && (is.na(threads) || threads >= 1L),
108-
length(cleanup) == 1L && is.logical(cleanup) && !is.na(cleanup)
109-
)
123+
with_assert({
124+
if (!is.null(immediateConditionHandlers)) {
125+
stop_if_not(is.list(immediateConditionHandlers))
126+
if (length(immediateConditionHandlers) > 0) {
127+
stop_if_not(
128+
!is.null(names(immediateConditionHandlers)),
129+
all(vapply(immediateConditionHandlers, FUN = is.function, FUN.VALUE = FALSE))
130+
)
131+
}
132+
}
133+
134+
stop_if_not(
135+
length(forwardOptions) == 0L || !is.null(names(forwardOptions)),
136+
length(local) == 1L && is.logical(local) && !is.na(local),
137+
length(stdout) == 1L && is.logical(stdout),
138+
length(split) == 1L && is.logical(split) && !is.na(split),
139+
is.null(conditionClasses) || (is.character(conditionClasses) && !anyNA(conditionClasses) && all(nzchar(conditionClasses))),
140+
is.character(immediateConditionClasses) && !anyNA(immediateConditionClasses) && all(nzchar(immediateConditionClasses)),
141+
is.null(seed) || is_lecyer_cmrg_seed(seed) || (is.logical(seed) && !is.na(seed) || !seed),
142+
is.character(backendPackages) && !anyNA(backendPackages) && all(nzchar(backendPackages)),
143+
length(threads) == 1L && is.integer(threads) && (is.na(threads) || threads >= 1L),
144+
length(cleanup) == 1L && is.logical(cleanup) && !is.na(cleanup)
145+
)
146+
})
147+
110148

111149
## Is it possible to force single-threaded processing?
112150
if (!is.na(threads)) {
@@ -127,22 +165,23 @@ evalFuture <- function(
127165
}
128166
}
129167

130-
131-
if (is.function(strategiesR)) {
132-
if (!inherits(strategiesR, "future")) {
133-
stop(FutureEvalError(sprintf("Argument 'strategiesR' is a function, but does not inherit 'future': %s", commaq(class(strategiesR)))))
134-
}
135-
} else if (is.list(strategiesR)) {
136-
for (kk in seq_along(strategiesR)) {
137-
strategy <- strategiesR[[kk]]
138-
if (!inherits(strategy, "future")) {
139-
stop(FutureEvalError(sprintf("Element #%d of list 'strategiesR' is a function, but does not inherit 'future': %s", kk, commaq(class(strategy)))))
168+
with_assert({
169+
if (is.function(strategiesR)) {
170+
if (!inherits(strategiesR, "future")) {
171+
stop(FutureEvalError(sprintf("Argument 'strategiesR' is a function, but does not inherit 'future': %s", commaq(class(strategiesR)))))
140172
}
173+
} else if (is.list(strategiesR)) {
174+
for (kk in seq_along(strategiesR)) {
175+
strategy <- strategiesR[[kk]]
176+
if (!inherits(strategy, "future")) {
177+
stop(FutureEvalError(sprintf("Element #%d of list 'strategiesR' is a function, but does not inherit 'future': %s", kk, commaq(class(strategy)))))
178+
}
179+
}
180+
} else if (is.character(strategiesR)) {
181+
} else {
182+
stop(FutureEvalError(sprintf("Unknown value of argument 'strategiesR': %s", commaq(class(strategiesR)))))
141183
}
142-
} else if (is.character(strategiesR)) {
143-
} else {
144-
stop(FutureEvalError(sprintf("Unknown value of argument 'strategiesR': %s", commaq(class(strategiesR)))))
145-
}
184+
})
146185

147186

148187

@@ -363,14 +402,6 @@ evalFuture <- function(
363402
## -----------------------------------------------------------------
364403
## Evaluate expression in a local() environment?
365404
if (local) {
366-
tmpl_expr_local <- bquote_compile(base::local({
367-
"# future:::evalFuture(): set convenient name of local environment"
368-
env <- environment()
369-
attr(env, "name") <- "future:evalenv"
370-
rm(list = "env", inherits = FALSE)
371-
372-
.(expr)
373-
}))
374405
expr <- bquote_apply(tmpl_expr_local)
375406
## WORKAROUND: This makes assumption about withCallingHandlers()
376407
## and local(). In case this changes, provide internal options to
@@ -567,12 +598,7 @@ evalFuture <- function(
567598
globalenv = if (globalenv) list(added = setdiff(names(.GlobalEnv), ...future.globalenv.names)) else NULL,
568599
started = ...future.startTime
569600
)
570-
}, condition = base::local({
571-
sysCalls <- function(calls = sys.calls(), from = 1L) {
572-
calls[seq.int(from = from + skip[1L], to = length(calls) - skip[2L])]
573-
}
574-
575-
function(cond) {
601+
}, condition = function(cond) {
576602
## Handle immediately?
577603
if (length(immediateConditionHandlers) > 0) {
578604
## Handle immediateCondition:s?
@@ -615,7 +641,9 @@ evalFuture <- function(
615641
system = Sys.info()
616642
)
617643
}
618-
644+
645+
sysCalls <- getSysCalls()
646+
619647
## Record condition
620648
...future.conditions[[length(...future.conditions) + 1L]] <<- list(
621649
condition = cond,
@@ -649,7 +677,7 @@ evalFuture <- function(
649677
}
650678
}
651679
} ## function(cond)
652-
})) ## local() + withCallingHandlers()
680+
) ## withCallingHandlers()
653681
}, error = function(ex) {
654682
FutureResult(
655683
conditions = ...future.conditions,

R/utils-prune_pkg_code.R

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
with_assert <- function(expr, ...) {
2+
invisible(expr)
3+
}
4+
15
prune_call <- function(expr, name) {
26
if (!is.call(expr))
37
return(expr)
@@ -10,8 +14,10 @@ prune_call <- function(expr, name) {
1014
NULL
1115
}
1216

13-
prune_stop_if_not <- function(expr) {
14-
prune_call(expr, name = "stop_if_not")
17+
prune_fcns <- function(expr) {
18+
expr <- prune_call(expr, name = "stop_if_not")
19+
expr <- prune_call(expr, name = "with_assert")
20+
expr
1521
}
1622

1723
#' @importFrom globals walkAST
@@ -21,7 +27,7 @@ prune_pkg_code <- function(env = topenv(parent.frame())) {
2127
if (exists(name, mode = "function", envir = env, inherits = FALSE)) {
2228
fcn <- get(name, mode = "function", envir = env, inherits = FALSE)
2329
body0 <- body(fcn)
24-
body <- walkAST(body0, call = prune_stop_if_not)
30+
body <- walkAST(body0, call = prune_fcns)
2531
if (!identical(body, body0)) {
2632
body(fcn) <- body
2733
assign(name, fcn, envir = env, inherits = FALSE)

R/utils_api-plan.R

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,17 @@ plan <- local({
284284
if (init) plan_init()
285285

286286
## Sanity checks
287-
nbrOfWorkers <- nbrOfWorkers()
288-
if (isTRUE(getOption("future.debug"))) {
289-
mdebugf(sprintf("plan(): nbrOfWorkers() = %.0f", nbrOfWorkers))
290-
}
291-
stop_if_not(is.numeric(nbrOfWorkers), length(nbrOfWorkers) == 1L,
292-
!is.na(nbrOfWorkers), nbrOfWorkers >= 1L)
287+
stop_if_not(
288+
nbrOfWorkers <- local({
289+
nbrOfWorkers <- nbrOfWorkers()
290+
if (isTRUE(getOption("future.debug"))) {
291+
mdebugf(sprintf("plan(): nbrOfWorkers() = %.0f", nbrOfWorkers))
292+
}
293+
nbrOfWorkers
294+
}),
295+
is.numeric(nbrOfWorkers), length(nbrOfWorkers) == 1L,
296+
!is.na(nbrOfWorkers), nbrOfWorkers >= 1L
297+
)
293298

294299
invisible(oldStack)
295300
} ## plan_set()

0 commit comments

Comments
 (0)