r-lib / cli

Tools for making beautiful & useful command line interfaces
https://cli.r-lib.org/
Other
653 stars 70 forks source link

Bottleneck when printing ansi colors in RStudio #607

Closed wlandau closed 1 year ago

wlandau commented 1 year ago

With https://github.com/r-lib/cli/commit/778f7d053a7901d1e9ea17cd6b6905b16217177a on Mac OS, system.time(replicate(1e3, print(cli::col_green))) completes in 0.125 seconds in the terminal and 3.384 seconds in the RStudio IDE. For the RStudio case, flame graphs with proffer seem to point to num_ansi_colors(), (mainly via rstudio$detect() and utils::readCitationFile()) as the main source of overhead (see below). For packages like targets, this overhead is noticeable because some projects generate a lot of messages.

Would it be possible for cli to pre-compute/cache the output of cli::num_ansi_colors() (maybe on load)? Unless I am missing something, it does not seem like ansi color data would change from R session to R session.

cli

gaborcsardi commented 1 year ago

No, it is not possible to precompute it, because it might change, e.g. the user can set an option, call sink(), etc.

However, if you know that it does not change, then you can cache it yourself. E.g. in the terminal:

❯ system.time(replicate(1e3, cli::col_green("foo")))
   user  system elapsed
  0.040   0.000   0.041

❯ options(cli.num_colors = cli::num_ansi_colors())
❯ system.time(replicate(1e3, cli::col_green("foo")))
   user  system elapsed
  0.009   0.000   0.009

And in RStudio:

> system.time(replicate(1e3, cli::col_green("foo")))
   user  system elapsed 
  0.903   0.149   1.053 

> options(cli.num_colors = cli::num_ansi_colors())
> system.time(replicate(1e3, cli::col_green("foo")))
   user  system elapsed 
  0.008   0.000   0.008 
wlandau commented 1 year ago

Thanks for explaining, that helps. Now that I know what to look for, I also see there is a cli.unicode option (for onlookers, c.f. https://github.com/r-lib/cli/issues/396).