Я поддерживаю пакет, который опирается на повторные звонки deparse(control = c("keepNA", "keepInteger"))
. control
всегда то же самое, и выражение меняется. deparse()
похоже, тратит много времени на многократную интерпретацию одного и того же набора параметров .deparseOpts()
.
microbenchmark::microbenchmark(
a = deparse(identity, control = c("keepNA", "keepInteger")),
b = .deparseOpts(c("keepNA", "keepInteger"))
)
# Unit: microseconds
# expr min lq mean median uq max neval
# a 7.2 7.4 8.020 7.5 7.6 55.1 100
# b 3.0 3.2 3.387 3.4 3.5 6.0 100
В некоторых системах избыточные .deparseOpts()
вызовы фактически занимают большую часть времени выполнения deparse()
( граф пламени здесь ).
Я действительно хотел бы просто позвонить .deparseOpts()
один раз и затем предоставить числовой код deparse()
, но это кажется невозможным без .Internal()
непосредственного вызова или вызова кода C, ни один из которых не является оптимальным с точки зрения разработки пакета.
deparse
# function (expr, width.cutoff = 60L, backtick = mode(expr) %in%
# c("call", "expression", "(", "function"),
# control = c("keepNA", "keepInteger", "niceNames",
# "showAttributes"), nlines = -1L)
# .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control),
# nlines))
# <bytecode: 0x0000000006ac27b8>
# <environment: namespace:base>
Есть ли удобный обходной путь?
backtick
вычисляю аргумент, разбор происходит в 6 раз быстрее! Я иду с этим. Большое спасибо за обходной путь!R CMD check
обнаруживает.Internal()
вызов в функциях, производимых (1). Довольно легко обойти, мне просто нужноmake_deparse()(expr, control = 64, backtick = TRUE)
. Глупо восстанавливать депарсер каждый раз, когда я его использую, но это все же намного быстрее, чем наивный, которыйdeparse()
я использовал раньше.make_deparse
иRun
функции в (1) и бегала ,R CMD build
иR CMD check --as-cran
под"R version 3.6.1 Patched (2019-11-18 r77437)"
и не жаловался , и мне не нужно никаких обходных путей. Вы уверены, что не делаете что-то другое или кроме того, что вызывает это?direct_deparse <- make_direct_deparse()
. Код, показанный в ответе, старался не делать этого и определял его только внутри функции, то есть внутриRun
.