Mantengo un paquete que se basa en llamadas repetidas a deparse(control = c("keepNA", "keepInteger"))
. control
es siempre igual, y la expresión varía. deparse()
parece pasar mucho tiempo interpretando repetidamente el mismo conjunto de opciones con .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
En algunos sistemas, las .deparseOpts()
llamadas redundantes en realidad ocupan la mayor parte del tiempo de ejecución de deparse()
( gráfico de llama aquí ).
Realmente me gustaría llamar .deparseOpts()
una vez y luego proporcionar el código numérico deparse()
, pero eso parece imposible sin llamar .Internal()
o invocar el código C directamente, ninguno de los cuales es óptimo desde la perspectiva del desarrollo del paquete.
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>
¿Hay una solución conveniente?
backtick
argumento, el análisis es 6 veces más rápido. Me voy con eso. Muchas gracias por la solución!R CMD check
detecta la.Internal()
llamada en funciones producidas por (1). Bastante fácil de solucionar, solo necesitomake_deparse()(expr, control = 64, backtick = TRUE)
. Es una tontería reconstruir el analizador cada vez que lo uso, pero aún es mucho más rápido que el ingenuodeparse()
que estaba usando antes.make_deparse
yRun
en (1) y ejecutéR CMD build
yR CMD check --as-cran
debajo"R version 3.6.1 Patched (2019-11-18 r77437)"
y no se quejó y no necesité ninguna solución. ¿Estás seguro de que no estás haciendo algo diferente o que además está causando esto?direct_deparse <- make_direct_deparse()
. El código que se muestra en la respuesta tuvo cuidado de no hacer eso y solo lo definió dentro de una función, es decir, dentroRun
.