$output function (x, options) { if (class == “output” && output_asis(x, options)) return(x) hook.t(x, options[[paste0(“attr.”, class)]], options[[paste0(“class.”, class)]]) } <bytecode: 0x560f27633bf0> <environment: 0x560f28058a00>

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         27.3µs   33.9µs    27834.    98.4KB     25.1
#> 2 plain       27.17µs     34µs    27787.        0B     25.0
#> 3 base         7.94µs   10.1µs    92175.    48.4KB     27.7
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         28.7µs   36.2µs    25616.        0B     28.2
#> 2 plain       27.99µs   35.8µs    25969.        0B     28.6
#> 3 base         9.18µs   11.7µs    79852.        0B     24.0

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        67.79µs  82.56µs    11305.   75.02KB     19.2
#> 2 plain       52.41µs  64.22µs    14709.    8.73KB     19.2
#> 3 base         1.56µs   1.79µs   503110.        0B     50.3

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          207µs    246µs     3881.   33.16KB     26.3
#> 2 plain         199µs    245µs     3900.    1.09KB     26.2

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          3.88µs   5.09µs   181164.    8.02KB     36.2
#>  2 fansi_ansi       19.42µs   23.5µs    39609.    4.18KB     31.7
#>  3 cli_plain         3.88µs   4.55µs   208240.        0B     20.8
#>  4 fansi_plain      19.38µs  22.08µs    42103.      688B     33.7
#>  5 cli_vec_ansi      4.98µs   5.69µs   160672.      448B     32.1
#>  6 fansi_vec_ansi   28.03µs  31.16µs    29833.    5.02KB     23.9
#>  7 cli_vec_plain     5.45µs   6.39µs   146539.      448B     29.3
#>  8 fansi_vec_plain  28.07µs  31.95µs    29175.    5.02KB     23.4
#>  9 cli_txt_ansi      3.88µs   4.67µs   194681.        0B     19.5
#> 10 fansi_txt_ansi   19.93µs   22.8µs    40497.      688B     32.4
#> 11 cli_txt_plain     4.68µs   5.43µs   173490.        0B     34.7
#> 12 fansi_txt_plain   27.8µs  32.34µs    27300.    5.02KB     21.9

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          54.2µs   60.9µs    15750.      22KB     8.22
#> 2 fansi        91.3µs  102.4µs     9186.    55.3KB    10.3

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          4.64µs   5.39µs   173715.        0B    34.7 
#>  2 fansi_ansi       49.79µs   59.2µs    15581.   38.83KB    25.9 
#>  3 base_ansi       640.87ns 710.95ns  1265360.        0B     0   
#>  4 cli_plain         4.54µs   5.37µs   170867.        0B    34.2 
#>  5 fansi_plain      48.99µs  58.55µs    15780.      688B    23.6 
#>  6 base_plain      599.89ns  665.9ns  1241474.        0B   124.  
#>  7 cli_vec_ansi     21.16µs  25.63µs    36555.      448B     3.66
#>  8 fansi_vec_ansi   67.51µs  77.85µs    11862.    5.02KB    19.3 
#>  9 base_vec_ansi       11µs  11.59µs    83321.      448B     0   
#> 10 cli_vec_plain    20.19µs  24.66µs    38070.      448B     7.62
#> 11 fansi_vec_plain  60.44µs  70.54µs    12945.    5.02KB    21.7 
#> 12 base_vec_plain    6.57µs   6.96µs   139272.      448B     0   
#> 13 cli_txt_ansi     21.78µs  25.99µs    37133.        0B     7.43
#> 14 fansi_txt_ansi   59.49µs  69.82µs    12875.      688B    19.0 
#> 15 base_txt_ansi       11µs  12.26µs    79360.        0B     7.94
#> 16 cli_txt_plain    18.63µs  23.59µs    40770.        0B     4.08
#> 17 fansi_txt_plain  51.84µs  58.65µs    15999.      688B    26.2 
#> 18 base_txt_plain    6.15µs   6.58µs   146703.        0B     0
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           5.4µs    6.4µs   145625.        0B    29.1 
#>  2 fansi_ansi        50.1µs  59.28µs    14794.      688B    23.8 
#>  3 base_ansi       924.92ns   1.03µs   863718.        0B     0   
#>  4 cli_plain         5.53µs   6.54µs   141033.        0B    28.2 
#>  5 fansi_plain      49.72µs  60.22µs    15385.      688B    25.9 
#>  6 base_plain      737.14ns 817.12ns  1101271.        0B     0   
#>  7 cli_vec_ansi     24.07µs  28.53µs    33292.      448B     6.66
#>  8 fansi_vec_ansi   74.16µs  85.56µs    10520.    5.02KB    17.1 
#>  9 base_vec_ansi    34.17µs   37.6µs    24586.      448B     0   
#> 10 cli_vec_plain    23.65µs  26.68µs    35338.      448B    10.6 
#> 11 fansi_vec_plain  65.84µs  76.87µs    12117.    5.02KB    19.3 
#> 12 base_vec_plain   18.22µs  19.23µs    49639.      448B     0   
#> 13 cli_txt_ansi     24.17µs   28.8µs    33390.        0B     6.68
#> 14 fansi_txt_ansi   65.71µs  75.57µs    12436.      688B    19.1 
#> 15 base_txt_ansi    36.01µs  39.33µs    24160.        0B     2.42
#> 16 cli_txt_plain    23.36µs  26.56µs    36360.        0B     7.27
#> 17 fansi_txt_plain  57.96µs  67.29µs    13939.      688B    21.3 
#> 18 base_txt_plain   19.11µs  20.71µs    46592.        0B     4.66

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        4.55µs   5.49µs   156319.        0B    31.3 
#> 2 cli_plain       4.22µs   4.89µs   190072.        0B    19.0 
#> 3 cli_vec_ansi   30.14µs  32.84µs    28947.      848B     5.79
#> 4 cli_vec_plain   7.47µs   8.47µs   110215.      848B    11.0 
#> 5 cli_txt_ansi   30.26µs  33.25µs    28715.        0B     5.74
#> 6 cli_txt_plain   5.01µs   5.82µs   158344.        0B    15.8

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          7.68µs   9.09µs   102759.        0B     30.8
#>  2 fansi_ansi       18.43µs  21.09µs    44080.    7.24KB     35.3
#>  3 cli_plain         7.57µs   9.13µs    95016.        0B     28.5
#>  4 fansi_plain      18.35µs  20.95µs    44731.      688B     31.3
#>  5 cli_vec_ansi     15.69µs  17.83µs    52214.      848B     15.7
#>  6 fansi_vec_ansi   39.91µs  44.81µs    21174.    5.41KB     17.1
#>  7 cli_vec_plain     9.82µs  11.24µs    83119.      848B     24.9
#>  8 fansi_vec_plain  26.42µs  29.08µs    32185.    4.59KB     25.8
#>  9 cli_txt_ansi     15.08µs  16.99µs    56721.        0B     17.0
#> 10 fansi_txt_ansi   32.37µs  35.89µs    25542.    5.12KB     17.9
#> 11 cli_txt_plain     8.53µs   9.78µs    96954.        0B     29.1
#> 12 fansi_txt_plain  19.47µs  22.75µs    37988.      688B     30.4

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         80.33µs   96.3µs     9631.  103.29KB    28.2 
#>  2 fansi_ansi       76.28µs  91.32µs    10358.  106.34KB    26.0 
#>  3 base_ansi         3.22µs   3.72µs   255633.      224B    25.6 
#>  4 cli_plain        78.02µs  94.22µs     9709.    8.09KB    26.0 
#>  5 fansi_plain      76.45µs  90.26µs    10502.    9.62KB    28.5 
#>  6 base_plain        2.83µs   3.25µs   277785.        0B    27.8 
#>  7 cli_vec_ansi      4.94ms   5.28ms      186.  823.77KB    36.7 
#>  8 fansi_vec_ansi  797.71µs 898.11µs     1039.  846.81KB    20.0 
#>  9 base_vec_ansi    116.8µs 134.44µs     7078.    22.7KB     4.16
#> 10 cli_vec_plain     4.92ms   5.34ms      183.  823.77KB    37.1 
#> 11 fansi_vec_plain 765.68µs 897.85µs      982.  845.98KB    19.5 
#> 12 base_vec_plain      83µs  93.25µs    10060.      848B     4.06
#> 13 cli_txt_ansi      2.62ms   2.93ms      331.    63.6KB     0   
#> 14 fansi_txt_ansi    1.13ms   1.22ms      798.   35.05KB     2.02
#> 15 base_txt_ansi   100.06µs 121.58µs     7851.   18.47KB     2.03
#> 16 cli_txt_plain     1.87ms      2ms      470.    63.6KB     0   
#> 17 fansi_txt_plain 368.39µs 409.81µs     2323.    30.6KB     6.17
#> 18 base_txt_plain   67.26µs   81.2µs    11810.   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          58.3µs   65.8µs    14177.   32.21KB    31.0 
#>  2 fansi_ansi        33.5µs   39.3µs    23758.   31.43KB    30.9 
#>  3 base_ansi        779.1ns  845.1ns  1020223.     4.2KB   102.  
#>  4 cli_plain         57.8µs   66.7µs    14026.        0B    30.5 
#>  5 fansi_plain       34.2µs   39.7µs    23219.      872B    30.2 
#>  6 base_plain         748ns  819.9ns  1071212.        0B     0   
#>  7 cli_vec_ansi     173.3µs  192.4µs     4950.   16.73KB    10.5 
#>  8 fansi_vec_ansi    86.2µs     97µs     9698.    5.59KB    14.8 
#>  9 base_vec_ansi     25.5µs   29.1µs    32817.      848B     0   
#> 10 cli_vec_plain    129.4µs  143.6µs     6677.   16.73KB    14.9 
#> 11 fansi_vec_plain   83.4µs   92.6µs    10306.    5.59KB    14.8 
#> 12 base_vec_plain    20.8µs   22.9µs    41158.      848B     4.12
#> 13 cli_txt_ansi      65.9µs   75.4µs    12471.        0B    25.9 
#> 14 fansi_txt_ansi    34.2µs   39.4µs    23365.      872B    30.4 
#> 15 base_txt_ansi    785.9ns    848ns   955999.        0B    95.6 
#> 16 cli_txt_plain     58.6µs   66.4µs    13980.        0B    28.6 
#> 17 fansi_txt_plain   33.9µs   37.9µs    24731.      872B    32.2 
#> 18 base_txt_plain   750.1ns  819.9ns  1046074.        0B   105.

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        190.85µs 218.47µs    4231.         0B     28.3
#>  2 fansi_ansi       60.91µs  70.06µs   12975.    97.33KB     28.4
#>  3 base_ansi        21.95µs  25.84µs   33351.         0B     30.0
#>  4 cli_plain       113.05µs 137.79µs    5899.         0B     21.5
#>  5 fansi_plain      60.65µs  70.41µs   12775.       872B     28.2
#>  6 base_plain       17.86µs  20.68µs   44258.         0B     31.0
#>  7 cli_vec_ansi     22.35ms   22.8ms      42.4    2.48KB     66.6
#>  8 fansi_vec_ansi  174.53µs 195.08µs    4826.     7.25KB     14.8
#>  9 base_vec_ansi     1.62ms   1.79ms     534.    48.18KB     30.2
#> 10 cli_vec_plain    12.62ms  13.19ms      71.9    2.48KB     42.3
#> 11 fansi_vec_plain 143.49µs 157.83µs    5950.     6.42KB     14.7
#> 12 base_vec_plain    1.15ms   1.28ms     763.     47.4KB     31.7
#> 13 cli_txt_ansi     18.47ms  19.38ms      49.2  507.59KB     13.0
#> 14 fansi_txt_ansi  164.41µs 182.75µs    5284.     6.77KB     12.5
#> 15 base_txt_ansi      1.4ms   1.62ms     594.   582.06KB     15.9
#> 16 cli_txt_plain     1.16ms   1.33ms     693.   369.84KB     13.3
#> 17 fansi_txt_plain 127.83µs 146.04µs    6022.     2.51KB     12.6
#> 18 base_txt_plain   919.2µs   1.07ms     896.   367.31KB     15.6

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          4.39µs   5.25µs   175557.    23.8KB    35.1 
#>  2 fansi_ansi       49.83µs  57.29µs    16260.   28.48KB    28.5 
#>  3 base_ansi       703.03ns  763.1ns  1149713.        0B     0   
#>  4 cli_plain         4.31µs   5.21µs   171178.        0B    34.2 
#>  5 fansi_plain      49.24µs  56.84µs    16123.    1.98KB    28.4 
#>  6 base_plain      688.95ns   1.21µs   822211.        0B    82.2 
#>  7 cli_vec_ansi     21.99µs  25.24µs    37603.     1.7KB     7.52
#>  8 fansi_vec_ansi   76.97µs  86.38µs    10943.    8.86KB    19.6 
#>  9 base_vec_ansi     5.08µs   5.55µs   169208.      848B     0   
#> 10 cli_vec_plain    17.86µs  20.42µs    46358.     1.7KB     9.27
#> 11 fansi_vec_plain  73.51µs  83.38µs    10863.    8.86KB    19.5 
#> 12 base_vec_plain    4.65µs   5.12µs   183618.      848B     0   
#> 13 cli_txt_ansi      4.38µs   5.29µs   166806.        0B    33.4 
#> 14 fansi_txt_ansi   48.15µs   55.7µs    16799.    1.98KB    29.5 
#> 15 base_txt_ansi     3.24µs   3.63µs   260033.        0B    26.0 
#> 16 cli_txt_plain     5.03µs   5.76µs   162886.        0B    32.6 
#> 17 fansi_txt_plain  48.16µs  53.99µs    17124.    1.98KB    28.4 
#> 18 base_txt_plain    2.21µs   2.34µs   400322.        0B    40.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        60.65µs  71.58µs   13048.    11.85KB    23.6 
#>  2 base_ansi        1.04µs   1.16µs  750841.         0B     0   
#>  3 cli_plain          49µs  57.78µs   15765.     8.73KB    21.4 
#>  4 base_plain       1.01µs    1.5µs  655136.         0B     0   
#>  5 cli_vec_ansi     3.21ms   5.03ms     211.   838.77KB    24.5 
#>  6 base_vec_ansi   59.16µs  65.77µs   12833.       848B     0   
#>  7 cli_vec_plain    1.83ms   2.07ms     438.    816.9KB    28.1 
#>  8 base_vec_plain  35.67µs  39.34µs   24460.       848B     2.45
#>  9 cli_txt_ansi     10.8ms  11.18ms      88.7  114.42KB     6.49
#> 10 base_txt_ansi   62.64µs  66.57µs   14465.         0B     0   
#> 11 cli_txt_plain  186.44µs  204.8µs    4614.    18.16KB     6.13
#> 12 base_txt_plain  32.73µs  35.47µs   26497.         0B     2.65

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         43.4µs   50.1µs    18603.        0B    30.4 
#>  2 base_ansi        11.2µs   13.1µs    70104.        0B    28.1 
#>  3 cli_plain        43.5µs   50.6µs    18305.        0B    28.1 
#>  4 base_plain       11.2µs     13µs    70684.        0B    28.3 
#>  5 cli_vec_ansi    113.7µs  126.9µs     7567.     7.2KB    12.6 
#>  6 base_vec_ansi    41.9µs   47.2µs    19143.    1.66KB     8.25
#>  7 cli_vec_plain     102µs  114.3µs     8279.     7.2KB    12.6 
#>  8 base_vec_plain   37.1µs   43.2µs    22012.    1.66KB     7.49
#>  9 cli_txt_ansi     93.9µs  101.7µs     9343.        0B    14.6 
#> 10 base_txt_ansi    26.3µs     29µs    32550.        0B    13.0 
#> 11 cli_txt_plain    79.4µs   87.7µs    10872.        0B    19.0 
#> 12 base_txt_plain   23.6µs   27.2µs    35080.        0B    10.5

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          5.42µs    6.4µs   140427.        0B    28.1 
#> 2 base       659.96ns    718ns  1227096.        0B     0   
#> 3 cli_vec     21.68µs   24.8µs    38928.      448B     7.79
#> 4 base_vec    10.26µs   11.1µs    87780.      448B     0   
#> 5 cli_txt     21.22µs   24.5µs    39175.        0B     7.84
#> 6 base_txt    11.75µs   13.3µs    74812.        0B     7.48
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          5.42µs    6.4µs   139323.        0B    27.9 
#> 2 base       977.07ns    1.1µs   798423.        0B     0   
#> 3 cli_vec     21.54µs   25.3µs    37414.      448B    11.2 
#> 4 base_vec    40.49µs   43.8µs    21939.      448B     0   
#> 5 cli_txt     21.94µs   24.9µs    38991.        0B     7.80
#> 6 base_txt    65.84µs   73.1µs    13186.        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          5.83µs   6.88µs   135078.        0B    27.0 
#> 2 base       655.88ns 725.97ns  1154697.        0B     0   
#> 3 cli_vec     15.94µs  17.85µs    53677.      448B    16.1 
#> 4 base_vec    10.58µs  11.36µs    86209.      448B     0   
#> 5 cli_txt     17.57µs  19.66µs    48790.        0B     9.76
#> 6 base_txt    11.87µs  12.93µs    75547.        0B     7.56

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          4.18µs   4.96µs   184950.    21.1KB    37.0 
#> 2 base       714.91ns 806.88ns  1036107.        0B     0   
#> 3 cli_vec     25.29µs  29.62µs    32318.     1.7KB     9.70
#> 4 base_vec     5.79µs   6.41µs   136934.      848B     0   
#> 5 cli_txt      4.18µs   4.97µs   186855.        0B    37.4 
#> 6 base_txt     4.74µs   5.36µs   176064.        0B     0

Session info

sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.1 (2024-06-14)
#>  os       Ubuntu 22.04.5 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en
#>  collate  en_US.UTF-8
#>  ctype    en_US.UTF-8
#>  tz       Etc/UTC
#>  date     2025-05-23
#>  pandoc   3.2 @ /usr/lib/rstudio-server/bin/quarto/bin/tools/x86_64/ (via rmarkdown)
#>  quarto   1.5.57 @ /usr/local/bin/quarto
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date (UTC) lib source
#>  bench         1.1.4   2025-01-16 [2] PRISM (R 4.4.1)
#>  bslib         0.9.0   2025-01-30 [2] PRISM (R 4.4.1)
#>  cachem        1.1.0   2024-05-16 [2] PRISM (R 4.4.1)
#>  cli         * 3.6.3   2025-05-23 [1] local
#>  codetools     0.2-20  2024-03-31 [3] CRAN (R 4.4.1)
#>  desc          1.4.3   2023-12-10 [2] PRISM (R 4.4.1)
#>  digest        0.6.37  2024-08-19 [2] PRISM (R 4.4.1)
#>  evaluate      1.0.3   2025-01-10 [2] PRISM (R 4.4.1)
#>  fansi       * 1.0.6   2023-12-08 [2] PRISM (R 4.4.1)
#>  fastmap       1.2.0   2024-05-15 [2] PRISM (R 4.4.1)
#>  fs            1.6.6   2025-04-12 [2] PRISM (R 4.4.1)
#>  glue          1.8.0   2024-09-30 [2] PRISM (R 4.4.1)
#>  htmltools     0.5.8.1 2024-04-04 [2] PRISM (R 4.4.1)
#>  htmlwidgets   1.6.4   2023-12-06 [2] PRISM (R 4.4.1)
#>  jquerylib     0.1.4   2021-04-26 [2] PRISM (R 4.4.1)
#>  jsonlite      2.0.0   2025-03-27 [2] PRISM (R 4.4.1)
#>  knitr         1.50    2025-03-16 [2] PRISM (R 4.4.1)
#>  lifecycle     1.0.4   2023-11-07 [2] PRISM (R 4.4.1)
#>  magrittr      2.0.3   2022-03-30 [2] PRISM (R 4.4.1)
#>  pillar        1.10.2  2025-04-05 [2] PRISM (R 4.4.1)
#>  pkgconfig     2.0.3   2019-09-22 [2] PRISM (R 4.4.1)
#>  pkgdown       2.1.1   2024-09-17 [2] PRISM (R 4.4.1)
#>  profmem       0.6.0   2020-12-13 [2] PRISM (R 4.4.1)
#>  R6            2.6.1   2025-02-15 [2] PRISM (R 4.4.1)
#>  ragg          1.4.0   2025-04-10 [2] PRISM (R 4.4.1)
#>  rlang         1.1.6   2025-04-11 [2] PRISM (R 4.4.1)
#>  rmarkdown     2.29    2024-11-04 [2] PRISM (R 4.4.1)
#>  rstudioapi    0.17.1  2024-10-22 [2] PRISM (R 4.4.1)
#>  sass          0.4.10  2025-04-11 [2] PRISM (R 4.4.1)
#>  sessioninfo   1.2.3   2025-02-05 [2] PRISM (R 4.4.1)
#>  systemfonts   1.2.2   2025-04-04 [2] PRISM (R 4.4.1)
#>  textshaping   1.0.0   2025-01-20 [2] PRISM (R 4.4.1)
#>  tibble        3.2.1   2023-03-20 [2] PRISM (R 4.4.1)
#>  utf8          1.2.4   2023-10-22 [2] PRISM (R 4.4.1)
#>  vctrs         0.6.5   2023-12-01 [2] PRISM (R 4.4.1)
#>  xfun          0.52    2025-04-02 [2] PRISM (R 4.4.1)
#>  yaml          2.3.10  2024-07-26 [2] PRISM (R 4.4.1)
#> 
#>  [1] /tmp/RtmprpRmPV/temp_libpath1378e63279977
#>  [2] /cluster-data/user-homes/elizabethb/projects/prism-pkgdocs-build/rv-toml-files/rv/library/4.4/x86_64/jammy
#>  [3] /opt/R/4.4.1/lib/R/library
#>  * ── Packages attached to the search path.
#> 
#> ──────────────────────────────────────────────────────────────────────────────