$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: 0x561c9ba430e8> <environment: 0x561c9c4674b8>

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        26.99µs   34.6µs    26668.    99.2KB     24.0
#> 2 plain        27.2µs   34.2µs    27125.        0B     27.2
#> 3 base         8.05µs   13.6µs    75703.    48.4KB     15.1
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.19µs   36.4µs    25424.        0B     28.0
#> 2 plain       27.27µs   35.9µs    25751.        0B     28.4
#> 3 base         9.06µs   11.6µs    80587.        0B     24.2

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.19µs  83.66µs    10704.   75.02KB     21.4
#> 2 plain       50.46µs  63.59µs    14383.    8.73KB     19.2
#> 3 base         1.53µs   1.76µs   505370.        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          203µs    243µs     3823.   33.16KB     26.3
#> 2 plain         205µs    285µs     3099.    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          4.04µs   5.47µs   171002.    9.19KB    34.2 
#>  2 fansi_ansi       19.25µs  24.23µs    37595.    4.18KB    30.1 
#>  3 cli_plain         4.06µs   4.72µs   197011.        0B    39.4 
#>  4 fansi_plain      19.35µs  21.86µs    41212.      688B    33.0 
#>  5 cli_vec_ansi       5.4µs   7.21µs   125670.      448B    25.1 
#>  6 fansi_vec_ansi   28.01µs  32.02µs    26493.    5.02KB    21.2 
#>  7 cli_vec_plain     6.25µs  10.41µs    96667.      448B     9.67
#>  8 fansi_vec_plain  27.09µs  31.96µs    27161.    5.02KB    24.5 
#>  9 cli_txt_ansi      4.01µs   4.84µs   187824.        0B    18.8 
#> 10 fansi_txt_ansi   19.45µs  22.29µs    40607.      688B    32.5 
#> 11 cli_txt_plain     5.24µs    7.7µs   122694.        0B    24.5 
#> 12 fansi_txt_plain   27.3µs  31.81µs    28007.    5.02KB    22.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          55.2µs   61.9µs    14926.    22.6KB     6.11
#> 2 fansi        89.7µs   98.3µs     9703.    55.3KB    10.4

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.72µs   5.53µs   168890.        0B    33.8 
#>  2 fansi_ansi       49.64µs  58.07µs    15785.   38.83KB    23.7 
#>  3 base_ansi       642.03ns 694.07ns  1133000.        0B   113.  
#>  4 cli_plain         4.66µs   5.41µs   172410.        0B    17.2 
#>  5 fansi_plain      49.75µs  58.93µs    15199.      688B    26.0 
#>  6 base_plain      588.01ns 623.99ns  1391018.        0B     0   
#>  7 cli_vec_ansi     20.67µs  24.45µs    39601.      448B     7.92
#>  8 fansi_vec_ansi   66.72µs  79.24µs    10925.    5.02KB    17.1 
#>  9 base_vec_ansi    10.72µs  12.93µs    72954.      448B     0   
#> 10 cli_vec_plain    20.29µs  23.49µs    40880.      448B     8.18
#> 11 fansi_vec_plain  60.18µs  70.28µs    13024.    5.02KB    21.8 
#> 12 base_vec_plain     6.4µs   6.79µs   141221.      448B     0   
#> 13 cli_txt_ansi     20.48µs  25.96µs    35402.        0B     7.08
#> 14 fansi_txt_ansi   59.05µs  68.34µs    13929.      688B    21.3 
#> 15 base_txt_ansi    11.05µs  12.23µs    79810.        0B     7.98
#> 16 cli_txt_plain    18.42µs  21.25µs    43795.        0B     4.38
#> 17 fansi_txt_plain  51.77µs  57.85µs    15982.      688B    26.4 
#> 18 base_txt_plain    6.14µs   6.73µs   134082.        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.63µs   6.53µs   129867.        0B    26.0 
#>  2 fansi_ansi       48.51µs  58.61µs    14961.      688B    23.9 
#>  3 base_ansi       910.83ns 969.97ns   851498.        0B    85.2 
#>  4 cli_plain         5.61µs   6.66µs   128948.        0B    25.8 
#>  5 fansi_plain      48.69µs  58.45µs    15693.      688B    25.9 
#>  6 base_plain      735.05ns 823.99ns  1056061.        0B     0   
#>  7 cli_vec_ansi     24.26µs  28.23µs    33223.      448B     6.65
#>  8 fansi_vec_ansi    73.6µs   84.9µs    10419.    5.02KB    17.1 
#>  9 base_vec_ansi    34.16µs  37.35µs    25383.      448B     0   
#> 10 cli_vec_plain    24.06µs  26.84µs    34480.      448B    10.3 
#> 11 fansi_vec_plain  65.35µs  78.45µs    10984.    5.02KB    17.1 
#> 12 base_vec_plain   18.18µs  19.17µs    46482.      448B     0   
#> 13 cli_txt_ansi     23.86µs  27.77µs    33700.        0B     6.74
#> 14 fansi_txt_ansi   65.47µs  75.87µs    11754.      688B    19.2 
#> 15 base_txt_ansi    35.34µs  39.09µs    24504.        0B     2.45
#> 16 cli_txt_plain    23.29µs  26.18µs    36365.        0B     7.27
#> 17 fansi_txt_plain  57.72µs  67.07µs    13790.      688B    21.3 
#> 18 base_txt_plain   19.18µs  20.63µs    46519.        0B     4.65

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.68µs   5.43µs   168774.        0B    33.8 
#> 2 cli_plain       4.34µs   7.02µs   139838.        0B    14.0 
#> 3 cli_vec_ansi   30.78µs  36.19µs    23334.      848B     4.67
#> 4 cli_vec_plain   8.17µs    9.4µs    96151.      848B     9.62
#> 5 cli_txt_ansi   31.22µs   33.8µs    28142.        0B     5.63
#> 6 cli_txt_plain   5.29µs   6.69µs   138709.        0B    27.7

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.78µs   9.26µs    99564.        0B     29.9
#>  2 fansi_ansi       17.92µs  20.89µs    44445.    7.24KB     35.6
#>  3 cli_plain         7.75µs   9.09µs   102018.        0B     30.6
#>  4 fansi_plain      17.81µs   20.8µs    44136.      688B     35.3
#>  5 cli_vec_ansi     16.64µs  18.97µs    50244.      848B     15.1
#>  6 fansi_vec_ansi    39.8µs  44.81µs    20290.    5.41KB     17.5
#>  7 cli_vec_plain    10.62µs  12.42µs    70411.      848B     21.1
#>  8 fansi_vec_plain  26.18µs  29.93µs    28639.    4.59KB     20.1
#>  9 cli_txt_ansi        16µs  17.96µs    51889.        0B     20.8
#> 10 fansi_txt_ansi   32.02µs  35.33µs    25540.    5.12KB     17.9
#> 11 cli_txt_plain      8.8µs  10.76µs    87773.        0B     35.1
#> 12 fansi_txt_plain  19.62µs  29.15µs    30536.      688B     21.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         79.64µs  94.35µs     9438.  104.31KB    28.4 
#>  2 fansi_ansi       75.15µs  89.11µs    10530.  106.34KB    28.5 
#>  3 base_ansi         3.08µs   3.57µs   264201.      224B     0   
#>  4 cli_plain        78.22µs  93.82µs     9608.    8.09KB    28.6 
#>  5 fansi_plain      75.25µs  92.48µs     9549.    9.62KB    23.9 
#>  6 base_plain         2.8µs   3.58µs   240573.        0B    24.1 
#>  7 cli_vec_ansi      4.95ms   5.32ms      187.  823.77KB    36.8 
#>  8 fansi_vec_ansi  763.39µs 901.81µs      987.  846.81KB    20.2 
#>  9 base_vec_ansi   116.25µs  131.6µs     7301.    22.7KB     4.16
#> 10 cli_vec_plain     4.91ms   5.34ms      179.  823.77KB    34.7 
#> 11 fansi_vec_plain 742.52µs 872.55µs     1053.  845.98KB    22.2 
#> 12 base_vec_plain   82.98µs   93.5µs     9219.      848B     4.06
#> 13 cli_txt_ansi      2.56ms   2.79ms      351.    63.6KB     0   
#> 14 fansi_txt_ansi    1.09ms   1.21ms      788.   35.05KB     2.02
#> 15 base_txt_ansi    97.07µs 121.84µs     7890.   18.47KB     2.03
#> 16 cli_txt_plain     1.71ms   1.99ms      495.    63.6KB     2.02
#> 17 fansi_txt_plain  365.9µs 411.55µs     2261.    30.6KB     6.19
#> 18 base_txt_plain   67.46µs  81.77µs    11002.   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          60.3µs   67.9µs    13536.   33.81KB     31.1
#>  2 fansi_ansi        33.8µs     39µs    23984.   31.43KB     31.2
#>  3 base_ansi          768ns    825ns  1006476.     4.2KB    101. 
#>  4 cli_plain         59.1µs   67.4µs    13736.        0B     30.5
#>  5 fansi_plain       33.8µs   39.3µs    22852.      872B     29.7
#>  6 base_plain       727.9ns  809.9ns  1032425.        0B      0  
#>  7 cli_vec_ansi     172.1µs  190.8µs     4684.   16.73KB     10.5
#>  8 fansi_vec_ansi    86.3µs   95.3µs     9398.    5.59KB     14.9
#>  9 base_vec_ansi     25.3µs   28.6µs    33574.      848B      0  
#> 10 cli_vec_plain    128.3µs  142.3µs     6533.   16.73KB     14.9
#> 11 fansi_vec_plain     82µs     94µs     9103.    5.59KB     14.9
#> 12 base_vec_plain    20.4µs   22.2µs    42895.      848B      0  
#> 13 cli_txt_ansi      67.5µs   76.9µs    12352.        0B     28.3
#> 14 fansi_txt_ansi    34.1µs   39.7µs    22152.      872B     28.8
#> 15 base_txt_ansi    787.1ns    848ns  1016130.        0B      0  
#> 16 cli_txt_plain     61.1µs   69.9µs    12783.        0B     29.4
#> 17 fansi_txt_plain   33.6µs   38.6µs    22596.      872B     29.4
#> 18 base_txt_plain     730ns  789.1ns  1125973.        0B    113.

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        186.39µs 216.64µs    4367.         0B     28.4
#>  2 fansi_ansi       60.11µs  68.97µs   13446.    97.33KB     30.9
#>  3 base_ansi        21.97µs  27.09µs   28466.         0B     22.8
#>  4 cli_plain       111.87µs  132.3µs    6586.         0B     26.1
#>  5 fansi_plain      59.75µs     70µs   12849.       872B     28.3
#>  6 base_plain       17.88µs  20.63µs   44572.         0B     31.2
#>  7 cli_vec_ansi     22.19ms  22.71ms      42.7    2.48KB     92.5
#>  8 fansi_vec_ansi  171.16µs 196.73µs    4391.     7.25KB     12.6
#>  9 base_vec_ansi      1.6ms   1.76ms     548.    48.18KB     30.4
#> 10 cli_vec_plain    12.33ms  13.14ms      74.9    2.48KB     48.5
#> 11 fansi_vec_plain 141.15µs 154.53µs    5928.     6.42KB     14.8
#> 12 base_vec_plain    1.13ms   1.29ms     700.     47.4KB     27.4
#> 13 cli_txt_ansi        18ms  18.92ms      52.1  507.59KB     16.5
#> 14 fansi_txt_ansi  162.45µs 177.24µs    5295.     6.77KB     12.5
#> 15 base_txt_ansi     1.36ms   1.59ms     611.   582.06KB     15.8
#> 16 cli_txt_plain     1.12ms   1.41ms     629.   369.84KB     13.3
#> 17 fansi_txt_plain 125.99µs 139.42µs    6540.     2.51KB     14.7
#> 18 base_txt_plain  902.26µs   1.05ms     908.   367.31KB     15.7

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.55µs   5.41µs   168953.   24.81KB    50.7 
#>  2 fansi_ansi       48.92µs  56.99µs    16090.   28.48KB    28.6 
#>  3 base_ansi       667.06ns 784.99ns  1085317.        0B     0   
#>  4 cli_plain         4.51µs   5.38µs   169428.        0B    33.9 
#>  5 fansi_plain      49.56µs     59µs    14501.    1.98KB    26.3 
#>  6 base_plain      666.01ns 722.01ns  1221028.        0B     0   
#>  7 cli_vec_ansi      21.9µs   24.8µs    37899.     1.7KB     7.58
#>  8 fansi_vec_ansi   76.53µs  86.18µs    10446.    8.86KB    19.7 
#>  9 base_vec_ansi     4.88µs   5.38µs   170803.      848B     0   
#> 10 cli_vec_plain    17.89µs  20.57µs    43984.     1.7KB    13.2 
#> 11 fansi_vec_plain  73.67µs  81.61µs    11343.    8.86KB    19.5 
#> 12 base_vec_plain    4.55µs   5.08µs   183033.      848B     0   
#> 13 cli_txt_ansi      4.53µs   5.49µs   166779.        0B    33.4 
#> 14 fansi_txt_ansi   48.82µs  54.97µs    15491.    1.98KB    29.6 
#> 15 base_txt_ansi     3.24µs   3.53µs   271102.        0B     0   
#> 16 cli_txt_plain     5.33µs   6.67µs   142571.        0B    28.5 
#> 17 fansi_txt_plain  48.17µs  54.01µs    17115.    1.98KB    30.9 
#> 18 base_txt_plain    2.21µs   2.46µs   370697.        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         61.3µs  71.98µs   12634.    11.85KB    23.8 
#>  2 base_ansi        1.03µs   1.12µs  813957.         0B     0   
#>  3 cli_plain       48.62µs  59.77µs   11790.     8.73KB    14.8 
#>  4 base_plain        812ns   1.49µs  630548.         0B     0   
#>  5 cli_vec_ansi     3.11ms    3.4ms     276.   838.77KB    35.1 
#>  6 base_vec_ansi    57.8µs   63.7µs   13226.       848B     0   
#>  7 cli_vec_plain    1.75ms   2.05ms     453.    816.9KB    31.1 
#>  8 base_vec_plain  35.61µs  38.77µs   23113.       848B     0   
#>  9 cli_txt_ansi    10.79ms  12.57ms      72.7  114.42KB     6.61
#> 10 base_txt_ansi   61.83µs  68.03µs   13343.         0B     0   
#> 11 cli_txt_plain  184.13µs 237.83µs    3799.    18.16KB     4.06
#> 12 base_txt_plain  32.41µs  36.46µs   24411.         0B     2.44

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.3µs   53.7µs    16088.        0B    26.1 
#>  2 base_ansi          11µs   13.4µs    65796.        0B    26.3 
#>  3 cli_plain        44.1µs   53.8µs    16584.        0B    28.4 
#>  4 base_plain       10.9µs   13.7µs    61470.        0B    24.6 
#>  5 cli_vec_ansi      115µs  139.3µs     6393.     7.2KB    10.5 
#>  6 base_vec_ansi    41.5µs   51.4µs    15946.    1.66KB     6.16
#>  7 cli_vec_plain   103.7µs  118.8µs     7651.     7.2KB    12.7 
#>  8 base_vec_plain   38.4µs   43.5µs    20878.    1.66KB     6.27
#>  9 cli_txt_ansi     95.9µs  106.4µs     8644.        0B    15.4 
#> 10 base_txt_ansi    26.3µs   29.3µs    30437.        0B    12.2 
#> 11 cli_txt_plain    81.9µs  123.7µs     8289.        0B    12.5 
#> 12 base_txt_plain   23.6µs   26.6µs    32364.        0B    13.0

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.56µs   6.52µs   135473.        0B    27.1 
#> 2 base       637.02ns 713.86ns  1177961.        0B   118.  
#> 3 cli_vec     23.16µs  25.85µs    37317.      448B     7.46
#> 4 base_vec    10.27µs  10.98µs    84597.      448B     0   
#> 5 cli_txt     22.29µs  25.89µs    37087.        0B     7.42
#> 6 base_txt    11.75µs  12.61µs    76886.        0B     7.69
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.5µs   6.52µs   137786.        0B    27.6 
#> 2 base        970.1ns   1.04µs   822694.        0B     0   
#> 3 cli_vec      22.1µs  25.82µs    34553.      448B    10.4 
#> 4 base_vec     39.5µs  42.42µs    22559.      448B     0   
#> 5 cli_txt      22.4µs  24.99µs    38159.        0B     7.63
#> 6 base_txt     64.3µs  74.74µs    12225.        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.82µs   6.79µs   131608.        0B     26.3
#> 2 base       643.08ns 744.01ns  1062396.        0B      0  
#> 3 cli_vec     15.68µs  17.82µs    52331.      448B     15.7
#> 4 base_vec    10.26µs  10.81µs    88683.      448B      0  
#> 5 cli_txt     17.23µs  18.85µs    50962.        0B     15.3
#> 6 base_txt    11.74µs  14.52µs    66531.        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          4.35µs   5.28µs   166688.    22.1KB    33.3 
#> 2 base       715.02ns 806.88ns  1039626.        0B   104.  
#> 3 cli_vec      26.3µs  29.16µs    33043.     1.7KB     6.61
#> 4 base_vec     5.79µs   6.18µs   150772.      848B     0   
#> 5 cli_txt      4.33µs   5.18µs   176763.        0B    53.0 
#> 6 base_txt     4.71µs   5.25µs   175206.        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-07
#>  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.5   2025-05-07 [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/RtmphFKOxG/temp_libpath720991ca0d34e
#>  [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.
#> 
#> ──────────────────────────────────────────────────────────────────────────────