Eu mantenho um pacote que depende de chamadas repetidas para deparse(control = c("keepNA", "keepInteger"))
. control
é sempre a mesma e a expressão varia. deparse()
parece gastar muito tempo interpretando repetidamente o mesmo conjunto de opções .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
Em alguns sistemas, as .deparseOpts()
chamadas redundantes ocupam a maior parte do tempo de execução de deparse()
( gráfico de chama aqui ).
Eu realmente gostaria de ligar apenas .deparseOpts()
uma vez e depois fornecer o código numérico deparse()
, mas isso parece impossível sem chamar .Internal()
ou invocar o código C diretamente, nenhum dos quais é ideal do ponto de vista do desenvolvimento de pacotes.
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>
Existe uma solução conveniente?
backtick
calculo o argumento, a separação é 6x mais rápida! Eu vou com isso. Muito obrigado pela solução alternativa!R CMD check
detecta a.Internal()
chamada nas funções produzidas por (1). Muito fácil de contornar, eu só precisomake_deparse()(expr, control = 64, backtick = TRUE)
. É tolice reconstruir o analisador toda vez que o uso, mas ainda é muito mais rápido do que o ingênuodeparse()
que estava usando antes.make_deparse
eRun
funções em (1) e correuR CMD build
eR CMD check --as-cran
sob"R version 3.6.1 Patched (2019-11-18 r77437)"
e não reclamar e eu não precisava de nenhuma solução alternativa. Tem certeza de que não está fazendo algo diferente ou que está causando isso?direct_deparse <- make_direct_deparse()
. O código mostrado na resposta teve o cuidado de não fazer isso e o definiu apenas dentro de uma função, ou seja, dentroRun
.