Skip to content

$output function (x, options) { hook.t(x, options[[paste0(“attr.”, class)]], options[[paste0(“class.”, class)]]) } <bytecode: 0x55bec969d2b0> <environment: 0x55becae9e768>

Introduction

Often we can use the corresponding base R function as a baseline. We also compare to the fansi package, where it is possible.

Data

In cli the typical use case is short string scalars, but we run some benchmarks longer strings and string vectors as well.

library(cli)
library(fansi)
options(cli.unicode = TRUE)
options(cli.num_colors = 256)
ansi <- format_inline(
  "{col_green(symbol$tick)} {.code print(x)} {.emph emphasised}"
)
plain <- ansi_strip(ansi)
vec_plain <- rep(plain, 100)
vec_ansi <- rep(ansi, 100)
vec_plain6 <- rep(plain, 6)
vec_ansi6 <- rep(plain, 6)
txt_plain <- paste(vec_plain, collapse = " ")
txt_ansi <- paste(vec_ansi, collapse = " ")
uni <- paste(
  "\U0001f477\u200d\u2640\ufe0f",
  "\U0001f477\U0001f3fb",
  "\U0001f477\u200d\u2640\ufe0f",
  "\U0001f477\U0001f3fb",
  "\U0001f477\U0001f3ff\u200d\u2640\ufe0f"
)
vec_uni <- rep(uni, 100)
txt_uni <- paste(vec_uni, collapse = " ")

ANSI functions

ansi_align()

bench::mark(
  ansi  = ansi_align(ansi, width = 20),
  plain = ansi_align(plain, width = 20), 
  base  = format(plain, width = 20),
  check = FALSE
)
#> # A tibble: 3 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ansi         47.8µs   51.2µs    19257.    97.8KB     21.4
#> 2 plain        48.2µs   51.4µs    18989.        0B     20.0
#> 3 base         12.3µs   13.5µs    72647.    48.4KB     21.8
bench::mark(
  ansi  = ansi_align(ansi, width = 20, align = "right"),
  plain = ansi_align(plain, width = 20, align = "right"), 
  base  = format(plain, width = 20, justify = "right"),
  check = FALSE
)
#> # A tibble: 3 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ansi           50µs   53.2µs    18466.        0B     21.6
#> 2 plain        49.6µs   52.9µs    18571.        0B     23.7
#> 3 base         14.6µs     16µs    61584.        0B     24.6

ansi_chartr()

bench::mark(
  ansi  = ansi_chartr("abc", "XYZ", ansi),
  plain = ansi_chartr("abc", "XYZ", plain),
  base  = chartr("abc", "XYZ", plain),
  check = FALSE
)
#> # A tibble: 3 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ansi       112.03µs 117.98µs     8340.   75.11KB     17.0
#> 2 plain       89.78µs  94.57µs    10392.    8.73KB     16.9
#> 3 base         1.87µs   2.01µs   479194.        0B      0

ansi_columns()

bench::mark(
  ansi  = ansi_columns(vec_ansi6, width = 120),
  plain = ansi_columns(vec_plain6, width = 120),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ansi          348µs    363µs     2717.    33.2KB     21.7
#> 2 plain         347µs    362µs     2724.    1.09KB     21.6

ansi_has_any()

bench::mark(
  cli_ansi        = ansi_has_any(ansi),
  fansi_ansi      = has_sgr(ansi),
  cli_plain       = ansi_has_any(plain),
  fansi_plain     = has_sgr(plain),
  cli_vec_ansi    = ansi_has_any(vec_ansi),
  fansi_vec_ansi  = has_sgr(vec_ansi),
  cli_vec_plain   = ansi_has_any(vec_plain),
  fansi_vec_plain = has_sgr(vec_plain),
  cli_txt_ansi    = ansi_has_any(txt_ansi),
  fansi_txt_ansi  = has_sgr(txt_ansi),
  cli_txt_plain   = ansi_has_any(txt_plain),
  fansi_txt_plain = has_sgr(vec_plain),
  check = FALSE
)
#> # A tibble: 12 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi          5.49µs   6.01µs   161975.    8.03KB     32.4
#>  2 fansi_ansi       30.85µs     34µs    28918.    4.18KB     26.0
#>  3 cli_plain         5.45µs   5.86µs   160977.        0B     16.1
#>  4 fansi_plain      30.58µs  32.41µs    30229.      688B     15.1
#>  5 cli_vec_ansi      6.75µs   7.18µs   136641.      448B     13.7
#>  6 fansi_vec_ansi   39.87µs  42.25µs    23122.    5.02KB     13.9
#>  7 cli_vec_plain     7.34µs   7.75µs   126197.      448B     12.6
#>  8 fansi_vec_plain  39.11µs  41.15µs    23927.    5.02KB     12.0
#>  9 cli_txt_ansi      5.44µs   5.86µs   167037.        0B     16.7
#> 10 fansi_txt_ansi   30.81µs  32.88µs    29866.      688B     14.9
#> 11 cli_txt_plain     6.29µs   6.72µs   146156.        0B     14.6
#> 12 fansi_txt_plain  38.62µs  40.86µs    24043.    5.02KB     14.4

ansi_html()

This is typically used with longer text.

bench::mark(
  cli   = ansi_html(txt_ansi),
  fansi = sgr_to_html(txt_ansi, classes = TRUE),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli          58.2µs   59.7µs    16550.    28.8KB     6.12
#> 2 fansi       123.4µs  127.2µs     7746.    55.4KB     4.06

ansi_nchar()

bench::mark(
  cli_ansi        = ansi_nchar(ansi),
  fansi_ansi      = nchar_sgr(ansi),
  base_ansi       = nchar(ansi),
  cli_plain       = ansi_nchar(plain),
  fansi_plain     = nchar_sgr(plain),
  base_plain      = nchar(plain),
  cli_vec_ansi    = ansi_nchar(vec_ansi),
  fansi_vec_ansi  = nchar_sgr(vec_ansi),
  base_vec_ansi   = nchar(vec_ansi),
  cli_vec_plain   = ansi_nchar(vec_plain),
  fansi_vec_plain = nchar_sgr(vec_plain),
  base_vec_plain  = nchar(vec_plain),
  cli_txt_ansi    = ansi_nchar(txt_ansi),
  fansi_txt_ansi  = nchar_sgr(txt_ansi),
  base_txt_ansi   = nchar(txt_ansi),
  cli_txt_plain   = ansi_nchar(txt_plain),
  fansi_txt_plain = nchar_sgr(txt_plain),
  base_txt_plain  = nchar(txt_plain),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi          6.98µs   7.56µs   129855.        0B    13.0 
#>  2 fansi_ansi       92.49µs   96.7µs    10195.   31.85KB    10.3 
#>  3 base_ansi       832.02ns 871.02ns  1079110.        0B   108.  
#>  4 cli_plain         6.97µs   7.56µs   129990.        0B    13.0 
#>  5 fansi_plain      91.94µs  95.99µs    10225.      688B    10.3 
#>  6 base_plain      781.03ns 821.08ns  1103989.        0B     0   
#>  7 cli_vec_ansi      28.9µs  29.93µs    33131.      448B     3.31
#>  8 fansi_vec_ansi  111.57µs 115.56µs     8534.    5.02KB     8.26
#>  9 base_vec_ansi    12.21µs   12.3µs    80508.      448B     8.05
#> 10 cli_vec_plain    27.53µs  28.22µs    35141.      448B     3.51
#> 11 fansi_vec_plain 101.72µs 105.88µs     9308.    5.02KB     8.26
#> 12 base_vec_plain    7.33µs    7.4µs   132921.      448B    13.3 
#> 13 cli_txt_ansi     28.95µs  29.89µs    33092.        0B     3.31
#> 14 fansi_txt_ansi  103.69µs 108.77µs     9067.      688B     8.22
#> 15 base_txt_ansi    11.61µs  11.66µs    84444.        0B     0   
#> 16 cli_txt_plain    27.14µs  27.81µs    35622.        0B     3.56
#> 17 fansi_txt_plain  94.23µs  98.29µs    10047.      688B    10.3 
#> 18 base_txt_plain    6.91µs   7.46µs   133585.        0B    13.4
bench::mark(
  cli_ansi        = ansi_nchar(ansi, type = "width"),
  fansi_ansi      = nchar_sgr(ansi, type = "width"),
  base_ansi       = nchar(ansi, "width"),
  cli_plain       = ansi_nchar(plain, type = "width"),
  fansi_plain     = nchar_sgr(plain, type = "width"),
  base_plain      = nchar(plain, "width"),
  cli_vec_ansi    = ansi_nchar(vec_ansi, type = "width"),
  fansi_vec_ansi  = nchar_sgr(vec_ansi, type = "width"),
  base_vec_ansi   = nchar(vec_ansi, "width"),
  cli_vec_plain   = ansi_nchar(vec_plain, type = "width"),
  fansi_vec_plain = nchar_sgr(vec_plain, type = "width"),
  base_vec_plain  = nchar(vec_plain, "width"),
  cli_txt_ansi    = ansi_nchar(txt_ansi, type = "width"),
  fansi_txt_ansi  = nchar_sgr(txt_ansi, type = "width"),
  base_txt_ansi   = nchar(txt_ansi, "width"),
  cli_txt_plain   = ansi_nchar(txt_plain, type = "width"),
  fansi_txt_plain = nchar_sgr(txt_plain, type = "width"),
  base_txt_plain  = nchar(txt_plain, type = "width"),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi           8.7µs    9.4µs   104631.        0B    10.5 
#>  2 fansi_ansi       93.29µs  97.27µs    10145.      688B    10.3 
#>  3 base_ansi         1.15µs    1.2µs   781330.        0B    78.1 
#>  4 cli_plain         8.72µs   9.42µs   104036.        0B    10.4 
#>  5 fansi_plain      91.71µs   96.3µs    10245.      688B    10.3 
#>  6 base_plain      962.06ns 993.14ns   927252.        0B     0   
#>  7 cli_vec_ansi     34.36µs  35.31µs    28001.      448B     5.60
#>  8 fansi_vec_ansi  118.27µs 122.31µs     8029.    5.02KB     8.26
#>  9 base_vec_ansi    37.66µs  37.92µs    26215.      448B     0   
#> 10 cli_vec_plain    33.48µs   34.3µs    28890.      448B     2.89
#> 11 fansi_vec_plain 107.69µs 111.85µs     8813.    5.02KB    10.4 
#> 12 base_vec_plain   19.21µs  19.46µs    51119.      448B     0   
#> 13 cli_txt_ansi     34.91µs  35.65µs    27730.        0B     2.77
#> 14 fansi_txt_ansi  109.43µs    114µs     8646.      688B    10.4 
#> 15 base_txt_ansi    40.26µs  40.41µs    24626.        0B     0   
#> 16 cli_txt_plain    33.42µs  34.29µs    28930.        0B     2.89
#> 17 fansi_txt_plain  99.62µs 104.78µs     9416.      688B    10.3 
#> 18 base_txt_plain   21.13µs   21.3µs    46637.        0B     0

ansi_simplify()

Nothing to compare here.

bench::mark(
  cli_ansi      = ansi_simplify(ansi),
  cli_plain     = ansi_simplify(plain),
  cli_vec_ansi  = ansi_simplify(vec_ansi),
  cli_vec_plain = ansi_simplify(vec_plain),
  cli_txt_ansi  = ansi_simplify(txt_ansi),
  cli_txt_plain = ansi_simplify(txt_plain),
  check = FALSE
)
#> # A tibble: 6 × 6
#>   expression         min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli_ansi        6.89µs   7.45µs   130770.        0B    26.2 
#> 2 cli_plain       6.42µs   6.97µs   141008.        0B    14.1 
#> 3 cli_vec_ansi   33.78µs  34.75µs    28512.      848B     2.85
#> 4 cli_vec_plain  10.36µs  11.01µs    89667.      848B     8.97
#> 5 cli_txt_ansi   33.12µs  34.09µs    29005.        0B     2.90
#> 6 cli_txt_plain   7.27µs   7.84µs   125409.        0B    12.5

ansi_strip()

bench::mark(
  cli_ansi        = ansi_strip(ansi),
  fansi_ansi      = strip_sgr(ansi),
  cli_plain       = ansi_strip(plain),
  fansi_plain     = strip_sgr(plain),
  cli_vec_ansi    = ansi_strip(vec_ansi),
  fansi_vec_ansi  = strip_sgr(vec_ansi),
  cli_vec_plain   = ansi_strip(vec_plain),
  fansi_vec_plain = strip_sgr(vec_plain),
  cli_txt_ansi    = ansi_strip(txt_ansi),
  fansi_txt_ansi  = strip_sgr(txt_ansi),
  cli_txt_plain   = ansi_strip(txt_plain),
  fansi_txt_plain = strip_sgr(txt_plain),
  check = FALSE
)
#> # A tibble: 12 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi          11.5µs   12.3µs    79586.        0B    15.9 
#>  2 fansi_ansi        28.7µs   30.8µs    31713.      688B    15.9 
#>  3 cli_plain         11.3µs   11.9µs    82261.        0B    16.5 
#>  4 fansi_plain       28.4µs   29.8µs    33002.      688B    16.5 
#>  5 cli_vec_ansi      20.1µs   20.9µs    47288.      848B     9.46
#>  6 fansi_vec_ansi    53.5µs   55.7µs    17760.    5.41KB     8.34
#>  7 cli_vec_plain       14µs   14.7µs    65039.      848B    13.0 
#>  8 fansi_vec_plain   36.9µs   38.7µs    25459.    4.59KB    12.7 
#>  9 cli_txt_ansi      19.8µs   20.7µs    47580.        0B     9.52
#> 10 fansi_txt_ansi      45µs   46.8µs    21047.    5.12KB    10.5 
#> 11 cli_txt_plain     12.1µs   12.9µs    70413.        0B    14.1 
#> 12 fansi_txt_plain   29.4µs   31.2µs    31587.      688B    15.8

ansi_strsplit()

bench::mark(
  cli_ansi        = ansi_strsplit(ansi, "i"),
  fansi_ansi      = strsplit_sgr(ansi, "i"),
  base_ansi       = strsplit(ansi, "i"),
  cli_plain       = ansi_strsplit(plain, "i"),
  fansi_plain     = strsplit_sgr(plain, "i"),
  base_plain      = strsplit(plain, "i"),
  cli_vec_ansi    = ansi_strsplit(vec_ansi, "i"),
  fansi_vec_ansi  = strsplit_sgr(vec_ansi, "i"),
  base_vec_ansi   = strsplit(vec_ansi, "i"),
  cli_vec_plain   = ansi_strsplit(vec_plain, "i"),
  fansi_vec_plain = strsplit_sgr(vec_plain, "i"),
  base_vec_plain  = strsplit(vec_plain, "i"),
  cli_txt_ansi    = ansi_strsplit(txt_ansi, "i"),
  fansi_txt_ansi  = strsplit_sgr(txt_ansi, "i"),
  base_txt_ansi   = strsplit(txt_ansi, "i"),
  cli_txt_plain   = ansi_strsplit(txt_plain, "i"),
  fansi_txt_plain = strsplit_sgr(txt_plain, "i"),
  base_txt_plain  = strsplit(txt_plain, "i"),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi        148.52µs  154.7µs     6366.  103.37KB    12.5 
#>  2 fansi_ansi      130.35µs 137.18µs     6856.  102.16KB    12.6 
#>  3 base_ansi          4.1µs   4.48µs   220558.      224B     0   
#>  4 cli_plain       146.99µs 153.32µs     6413.    8.09KB    12.5 
#>  5 fansi_plain     128.18µs 134.98µs     7252.    9.62KB    12.6 
#>  6 base_plain        3.61µs   3.85µs   255396.        0B     0   
#>  7 cli_vec_ansi      7.44ms   7.62ms      131.  823.77KB    16.7 
#>  8 fansi_vec_ansi    1.08ms   1.11ms      878.  846.81KB    15.1 
#>  9 base_vec_ansi   156.16µs 161.31µs     6102.    22.7KB     2.03
#> 10 cli_vec_plain     7.48ms   7.62ms      131.  823.77KB    16.7 
#> 11 fansi_vec_plain   1.01ms   1.05ms      941.  845.98KB    17.7 
#> 12 base_vec_plain  109.03µs 112.68µs     8747.      848B     4.07
#> 13 cli_txt_ansi      3.35ms    3.4ms      293.    63.6KB     0   
#> 14 fansi_txt_ansi    1.54ms   1.56ms      628.   35.05KB     0   
#> 15 base_txt_ansi   139.56µs 148.21µs     6711.   18.47KB     2.02
#> 16 cli_txt_plain     2.39ms   2.42ms      405.    63.6KB     2.02
#> 17 fansi_txt_plain  514.1µs 523.03µs     1882.    30.6KB     2.02
#> 18 base_txt_plain   91.31µs  94.53µs    10360.   11.05KB     2.02

ansi_strtrim()

bench::mark(
  cli_ansi        = ansi_strtrim(ansi, 10),
  fansi_ansi      = strtrim_sgr(ansi, 10),
  base_ansi       = strtrim(ansi, 10),
  cli_plain       = ansi_strtrim(plain, 10),
  fansi_plain     = strtrim_sgr(plain, 10),
  base_plain      = strtrim(plain, 10),
  cli_vec_ansi    = ansi_strtrim(vec_ansi, 10),
  fansi_vec_ansi  = strtrim_sgr(vec_ansi, 10),
  base_vec_ansi   = strtrim(vec_ansi, 10),
  cli_vec_plain   = ansi_strtrim(vec_plain, 10),
  fansi_vec_plain = strtrim_sgr(vec_plain, 10),
  base_vec_plain  = strtrim(vec_plain, 10),
  cli_txt_ansi    = ansi_strtrim(txt_ansi, 10),
  fansi_txt_ansi  = strtrim_sgr(txt_ansi, 10),
  base_txt_ansi   = strtrim(txt_ansi, 10),
  cli_txt_plain   = ansi_strtrim(txt_plain, 10),
  fansi_txt_plain = strtrim_sgr(txt_plain, 10),
  base_txt_plain  = strtrim(txt_plain, 10),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi         98.29µs 103.25µs     9480.   32.25KB    12.5 
#>  2 fansi_ansi       54.38µs  58.23µs    16535.   31.45KB    15.0 
#>  3 base_ansi         1.04µs   1.08µs   865164.     4.2KB     0   
#>  4 cli_plain        96.99µs 101.75µs     9582.        0B    14.6 
#>  5 fansi_plain      54.42µs  57.75µs    16965.      872B    12.5 
#>  6 base_plain      981.96ns   1.03µs   912415.        0B     0   
#>  7 cli_vec_ansi    223.19µs 228.74µs     4323.   16.73KB     6.16
#>  8 fansi_vec_ansi  120.62µs 124.57µs     7916.    5.59KB     9.54
#>  9 base_vec_ansi    33.46µs   33.7µs    29407.      848B     0   
#> 10 cli_vec_plain   179.02µs 183.96µs     5315.   16.73KB     6.17
#> 11 fansi_vec_plain 115.58µs 118.66µs     8319.    5.59KB     8.29
#> 12 base_vec_plain   28.37µs  28.58µs    34058.      848B     0   
#> 13 cli_txt_ansi    104.78µs 108.13µs     9126.        0B    12.4 
#> 14 fansi_txt_ansi   53.34µs  55.54µs    17688.      872B    14.8 
#> 15 base_txt_ansi     1.07µs   1.11µs   840169.        0B     0   
#> 16 cli_txt_plain    97.95µs 101.86µs     9699.        0B    14.6 
#> 17 fansi_txt_plain  53.21µs  56.45µs    17497.      872B    14.6 
#> 18 base_txt_plain    1.01µs   1.04µs   906875.        0B     0

ansi_strwrap()

This function is most useful for longer text, but it is often called for short text in cli, so it makes sense to benchmark that as well.

bench::mark(
  cli_ansi        = ansi_strwrap(ansi, 30),
  fansi_ansi      = strwrap_sgr(ansi, 30),
  base_ansi       = strwrap(ansi, 30),
  cli_plain       = ansi_strwrap(plain, 30),
  fansi_plain     = strwrap_sgr(plain, 30),
  base_plain      = strwrap(plain, 30),
  cli_vec_ansi    = ansi_strwrap(vec_ansi, 30),
  fansi_vec_ansi  = strwrap_sgr(vec_ansi, 30),
  base_vec_ansi   = strwrap(vec_ansi, 30),
  cli_vec_plain   = ansi_strwrap(vec_plain, 30),
  fansi_vec_plain = strwrap_sgr(vec_plain, 30),
  base_vec_plain  = strwrap(vec_plain, 30),
  cli_txt_ansi    = ansi_strwrap(txt_ansi, 30),
  fansi_txt_ansi  = strwrap_sgr(txt_ansi, 30),
  base_txt_ansi   = strwrap(txt_ansi, 30),
  cli_txt_plain   = ansi_strwrap(txt_plain, 30),
  fansi_txt_plain = strwrap_sgr(txt_plain, 30),
  base_txt_plain  = strwrap(txt_plain, 30),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi        330.04µs 340.41µs    2897.   266.74KB    12.5 
#>  2 fansi_ansi       96.26µs 101.77µs    9651.     10.3KB    14.6 
#>  3 base_ansi        39.98µs  42.03µs   23394.         0B    11.7 
#>  4 cli_plain       205.27µs    211µs    4657.         0B    12.4 
#>  5 fansi_plain       95.1µs 100.92µs    9773.       872B    12.5 
#>  6 base_plain          33µs  34.88µs   28169.         0B    14.1 
#>  7 cli_vec_ansi     34.23ms   34.5ms      28.5    2.48KB    21.4 
#>  8 fansi_vec_ansi  238.85µs 244.62µs    4031.     7.25KB     6.15
#>  9 base_vec_ansi     2.27ms   2.34ms     426.    48.18KB    15.2 
#> 10 cli_vec_plain    20.66ms     21ms      47.6    2.48KB    16.8 
#> 11 fansi_vec_plain 202.21µs 207.54µs    4699.     6.42KB     8.26
#> 12 base_vec_plain    1.64ms   1.68ms     590.     47.4KB    15.1 
#> 13 cli_txt_ansi     21.66ms  21.93ms      45.5  507.59KB     6.82
#> 14 fansi_txt_ansi  228.59µs 234.47µs    4215.     6.77KB     6.14
#> 15 base_txt_ansi     2.07ms    2.1ms     464.   582.06KB     8.56
#> 16 cli_txt_plain     1.64ms   1.69ms     588.   369.84KB     6.34
#> 17 fansi_txt_plain 180.54µs 187.24µs    5123.     2.51KB     8.27
#> 18 base_txt_plain    1.32ms   1.35ms     733.   367.31KB     7.31

ansi_substr()

bench::mark(
  cli_ansi        = ansi_substr(ansi, 2, 10),
  fansi_ansi      = substr_sgr(ansi, 2, 10),
  base_ansi       = substr(ansi, 2, 10),
  cli_plain       = ansi_substr(plain, 2, 10),
  fansi_plain     = substr_sgr(plain, 2, 10),
  base_plain      = substr(plain, 2, 10),
  cli_vec_ansi    = ansi_substr(vec_ansi, 2, 10),
  fansi_vec_ansi  = substr_sgr(vec_ansi, 2, 10),
  base_vec_ansi   = substr(vec_ansi, 2, 10),
  cli_vec_plain   = ansi_substr(vec_plain, 2, 10),
  fansi_vec_plain = substr_sgr(vec_plain, 2, 10),
  base_vec_plain  = substr(vec_plain, 2, 10),
  cli_txt_ansi    = ansi_substr(txt_ansi, 2, 10),
  fansi_txt_ansi  = substr_sgr(txt_ansi, 2, 10),
  base_txt_ansi   = substr(txt_ansi, 2, 10),
  cli_txt_plain   = ansi_substr(txt_plain, 2, 10),
  fansi_txt_plain = substr_sgr(txt_plain, 2, 10),
  base_txt_plain  = substr(txt_plain, 2, 10),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi          6.57µs      7µs   140338.   23.84KB    28.1 
#>  2 fansi_ansi       77.09µs   80.1µs    11883.   28.48KB    12.5 
#>  3 base_ansi       981.96ns   1.02µs   929272.        0B     0   
#>  4 cli_plain         6.25µs   6.87µs   143623.        0B    28.7 
#>  5 fansi_plain      75.89µs  79.05µs    12378.    1.98KB    12.5 
#>  6 base_plain      961.01ns      1µs   941241.        0B     0   
#>  7 cli_vec_ansi     27.15µs  27.82µs    35682.     1.7KB     7.14
#>  8 fansi_vec_ansi  113.02µs 117.59µs     8312.    8.86KB     8.39
#>  9 base_vec_ansi      5.9µs   6.54µs   150334.      848B    15.0 
#> 10 cli_vec_plain    22.72µs  23.73µs    41803.     1.7KB     4.18
#> 11 fansi_vec_plain 108.56µs 112.32µs     8776.    8.86KB    10.5 
#> 12 base_vec_plain     5.6µs   6.28µs   157660.      848B     0   
#> 13 cli_txt_ansi      6.46µs   7.04µs   139607.        0B    14.0 
#> 14 fansi_txt_ansi   77.27µs  81.68µs    12083.    1.98KB    14.7 
#> 15 base_txt_ansi     3.83µs   3.89µs   253753.        0B     0   
#> 16 cli_txt_plain      7.3µs   7.88µs   124821.        0B    12.5 
#> 17 fansi_txt_plain  77.08µs  81.16µs    12154.    1.98KB    14.7 
#> 18 base_txt_plain    2.63µs   2.69µs   363383.        0B     0

ansi_tolower() , ansi_toupper()

bench::mark(
  cli_ansi        = ansi_tolower(ansi),
  base_ansi       = tolower(ansi),
  cli_plain       = ansi_tolower(plain),
  base_plain      = tolower(plain),
  cli_vec_ansi    = ansi_tolower(vec_ansi),
  base_vec_ansi   = tolower(vec_ansi),
  cli_vec_plain   = ansi_tolower(vec_plain),
  base_vec_plain  = tolower(vec_plain),
  cli_txt_ansi    = ansi_tolower(txt_ansi),
  base_txt_ansi   = tolower(txt_ansi),
  cli_txt_plain   = ansi_tolower(txt_plain),
  base_txt_plain  = tolower(txt_plain),
  check = FALSE
)
#> # A tibble: 12 × 6
#>    expression          min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>     <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi       104.97µs 109.95µs    8912.    11.87KB    10.3 
#>  2 base_ansi        1.29µs   1.33µs  735664.         0B     0   
#>  3 cli_plain       84.35µs  88.02µs   11193.     8.73KB     8.21
#>  4 base_plain          1µs   1.04µs  910025.         0B     0   
#>  5 cli_vec_ansi     3.98ms   4.08ms     240.   838.77KB    18.3 
#>  6 base_vec_ansi   72.84µs  74.15µs   13375.       848B     0   
#>  7 cli_vec_plain    2.22ms   2.27ms     436.    816.9KB    20.0 
#>  8 base_vec_plain  43.86µs  44.52µs   22386.       848B     0   
#>  9 cli_txt_ansi    11.57ms  11.66ms      85.7  114.42KB     4.18
#> 10 base_txt_ansi   73.67µs  75.18µs   13323.         0B     0   
#> 11 cli_txt_plain  242.77µs 248.15µs    3978.    18.16KB     4.06
#> 12 base_txt_plain  42.25µs  43.18µs   23236.         0B     0

ansi_trimws()

bench::mark(
  cli_ansi        = ansi_trimws(ansi),
  base_ansi       = trimws(ansi),
  cli_plain       = ansi_trimws(plain),
  base_plain      = trimws(plain),
  cli_vec_ansi    = ansi_trimws(vec_ansi),
  base_vec_ansi   = trimws(vec_ansi),
  cli_vec_plain   = ansi_trimws(vec_plain),
  base_vec_plain  = trimws(vec_plain),
  cli_txt_ansi    = ansi_trimws(txt_ansi),
  base_txt_ansi   = trimws(txt_ansi),
  cli_txt_plain   = ansi_trimws(txt_plain),
  base_txt_plain  = trimws(txt_plain),
  check = FALSE
)
#> # A tibble: 12 × 6
#>    expression          min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>     <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi         76.5µs   79.8µs    12348.        0B    14.6 
#>  2 base_ansi        17.4µs   18.7µs    52556.        0B    10.5 
#>  3 cli_plain          76µs   79.6µs    12329.        0B    14.6 
#>  4 base_plain       17.8µs   18.9µs    51981.        0B    10.4 
#>  5 cli_vec_ansi    156.7µs  161.7µs     6083.     7.2KB     6.15
#>  6 base_vec_ansi    51.1µs   56.9µs    17312.    1.66KB     4.07
#>  7 cli_vec_plain   143.8µs  149.1µs     6577.     7.2KB     8.26
#>  8 base_vec_plain   49.4µs   53.4µs    17930.    1.66KB     4.10
#>  9 cli_txt_ansi    133.7µs    138µs     7155.        0B     8.19
#> 10 base_txt_ansi    35.9µs   37.2µs    26533.        0B     5.31
#> 11 cli_txt_plain   118.9µs  121.8µs     8087.        0B     8.20
#> 12 base_txt_plain   33.1µs   34.2µs    28889.        0B     8.67

UTF-8 functions

utf8_nchar()

bench::mark(
  cli        = utf8_nchar(uni, type = "chars"),
  base       = nchar(uni, "chars"),
  cli_vec    = utf8_nchar(vec_uni, type = "chars"),
  base_vec   = nchar(vec_uni, "chars"),
  cli_txt    = utf8_nchar(txt_uni, type = "chars"),
  base_txt   = nchar(txt_uni, "chars"),
  check = FALSE
)
#> # A tibble: 6 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli          8.48µs    9.1µs   107978.    12.3KB    10.8 
#> 2 base       840.98ns    891ns  1026287.        0B   103.  
#> 3 cli_vec     25.04µs     26µs    38121.      448B     3.81
#> 4 base_vec    11.34µs   11.5µs    85986.      448B     0   
#> 5 cli_txt      25.8µs   26.5µs    37265.        0B     7.45
#> 6 base_txt    12.55µs   12.6µs    78710.        0B     0
bench::mark(
  cli        = utf8_nchar(uni, type = "width"),
  base       = nchar(uni, "width"),
  cli_vec    = utf8_nchar(vec_uni, type = "width"),
  base_vec   = nchar(vec_uni, "width"),
  cli_txt    = utf8_nchar(txt_uni, type = "width"),
  base_txt   = nchar(txt_uni, "width"),
  check = FALSE
)
#> # A tibble: 6 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli          8.36µs   8.97µs   109605.        0B    11.0 
#> 2 base         1.26µs   1.31µs   716669.        0B    71.7 
#> 3 cli_vec     29.17µs  30.05µs    32911.      448B     3.29
#> 4 base_vec    47.41µs  47.66µs    20799.      448B     0   
#> 5 cli_txt     29.94µs  31.15µs    31663.        0B     6.33
#> 6 base_txt    82.58µs   83.4µs    11892.        0B     0
bench::mark(
  cli        = utf8_nchar(uni, type = "codepoints"),
  base       = nchar(uni, "chars"),
  cli_vec    = utf8_nchar(vec_uni, type = "codepoints"),
  base_vec   = nchar(vec_uni, "chars"),
  cli_txt    = utf8_nchar(txt_uni, type = "codepoints"),
  base_txt   = nchar(txt_uni, "chars"),
  check = FALSE
)
#> # A tibble: 6 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli          9.16µs   9.77µs   101152.        0B    20.2 
#> 2 base       842.03ns 882.08ns  1080992.        0B     0   
#> 3 cli_vec      19.9µs  20.58µs    47150.      448B     4.72
#> 4 base_vec    11.34µs  11.52µs    86114.      448B     0   
#> 5 cli_txt     20.92µs  21.48µs    46175.        0B     9.24
#> 6 base_txt    12.55µs  12.61µs    78682.        0B     0

utf8_substr()

bench::mark(
  cli        = utf8_substr(uni, 2, 10),
  base       = substr(uni, 2, 10),
  cli_vec    = utf8_substr(vec_uni, 2, 10),
  base_vec   = substr(vec_uni, 2, 10),
  cli_txt    = utf8_substr(txt_uni, 2, 10),
  base_txt   = substr(txt_uni, 2, 10),
  check = FALSE
)
#> # A tibble: 6 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cli           6.2µs   6.64µs   147795.    21.1KB    29.6 
#> 2 base            1µs   1.04µs   906737.        0B     0   
#> 3 cli_vec     30.86µs  31.62µs    31221.     1.7KB     6.25
#> 4 base_vec      7.7µs   7.91µs   125507.      848B     0   
#> 5 cli_txt      6.12µs   6.55µs   150343.        0B    15.0 
#> 6 base_txt     5.46µs   5.52µs   178579.        0B     0

Session info

sessioninfo::session_info()
#> ─ Session info ─────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.3.3 (2024-02-29)
#>  os       Ubuntu 22.04.4 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en
#>  collate  C.UTF-8
#>  ctype    C.UTF-8
#>  tz       UTC
#>  date     2024-04-23
#>  pandoc   3.1.11 @ /opt/hostedtoolcache/pandoc/3.1.11/x64/ (via rmarkdown)
#> 
#> ─ Packages ─────────────────────────────────────────────────────────────
#>  package     * version    date (UTC) lib source
#>  bench         1.1.3      2023-05-04 [1] RSPM
#>  bslib         0.7.0      2024-03-29 [1] RSPM
#>  cachem        1.0.8      2023-05-01 [1] RSPM
#>  cli         * 3.6.2.9000 2024-04-23 [1] local
#>  codetools     0.2-19     2023-02-01 [3] CRAN (R 4.3.3)
#>  desc          1.4.3      2023-12-10 [1] RSPM
#>  digest        0.6.35     2024-03-11 [1] RSPM
#>  evaluate      0.23       2023-11-01 [1] RSPM
#>  fansi       * 1.0.6      2023-12-08 [1] RSPM
#>  fastmap       1.1.1      2023-02-24 [1] RSPM
#>  fs            1.6.3      2023-07-20 [1] RSPM
#>  glue          1.7.0      2024-01-09 [1] RSPM
#>  htmltools     0.5.8.1    2024-04-04 [1] RSPM
#>  htmlwidgets   1.6.4      2023-12-06 [1] RSPM
#>  jquerylib     0.1.4      2021-04-26 [1] RSPM
#>  jsonlite      1.8.8      2023-12-04 [1] RSPM
#>  knitr         1.46       2024-04-06 [1] RSPM
#>  lifecycle     1.0.4      2023-11-07 [1] RSPM
#>  magrittr      2.0.3      2022-03-30 [1] RSPM
#>  memoise       2.0.1      2021-11-26 [1] RSPM
#>  pillar        1.9.0      2023-03-22 [1] RSPM
#>  pkgconfig     2.0.3      2019-09-22 [1] RSPM
#>  pkgdown       2.0.9      2024-04-18 [1] any (@2.0.9)
#>  profmem       0.6.0      2020-12-13 [1] RSPM
#>  purrr         1.0.2      2023-08-10 [1] RSPM
#>  R6            2.5.1      2021-08-19 [1] RSPM
#>  ragg          1.3.0      2024-03-13 [1] RSPM
#>  rlang         1.1.3      2024-01-10 [1] RSPM
#>  rmarkdown     2.26       2024-03-05 [1] RSPM
#>  sass          0.4.9      2024-03-15 [1] RSPM
#>  sessioninfo   1.2.2      2021-12-06 [1] RSPM
#>  systemfonts   1.0.6      2024-03-07 [1] RSPM
#>  textshaping   0.3.7      2023-10-09 [1] RSPM
#>  tibble        3.2.1      2023-03-20 [1] RSPM
#>  utf8          1.2.4      2023-10-22 [1] RSPM
#>  vctrs         0.6.5      2023-12-01 [1] RSPM
#>  xfun          0.43       2024-03-25 [1] RSPM
#>  yaml          2.3.8      2023-12-11 [1] RSPM
#> 
#>  [1] /home/runner/work/_temp/Library
#>  [2] /opt/R/4.3.3/lib/R/site-library
#>  [3] /opt/R/4.3.3/lib/R/library
#> 
#> ────────────────────────────────────────────────────────────────────────