Skip to content

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

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         44.2µs   47.6µs    20643.    98.4KB     21.0
#> 2 plain        44.4µs   47.8µs    20580.        0B     21.8
#> 3 base         11.5µs   12.7µs    77160.    48.4KB     23.2
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           46µs   49.6µs    19828.        0B     25.7
#> 2 plain        45.8µs   49.2µs    19882.        0B     23.4
#> 3 base         13.5µs   14.7µs    66880.        0B     26.8

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        111.3µs 117.78µs     8338.   75.02KB     16.8
#> 2 plain        89.2µs  94.04µs    10467.    8.73KB     14.6
#> 3 base          1.9µs   2.04µs   474908.        0B     47.5

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          330µs    346µs     2860.   33.16KB     21.3
#> 2 plain         329µs    344µs     2876.    1.09KB     21.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          5.56µs   6.08µs   159584.    8.02KB     31.9
#>  2 fansi_ansi       30.36µs  33.07µs    29700.    4.18KB     26.8
#>  3 cli_plain         5.49µs   5.83µs   168546.        0B     33.7
#>  4 fansi_plain      30.48µs     32µs    30760.      688B     24.6
#>  5 cli_vec_ansi      6.81µs   7.18µs   136334.      448B     27.3
#>  6 fansi_vec_ansi   40.01µs  41.84µs    23357.    5.02KB     21.0
#>  7 cli_vec_plain     7.38µs   7.79µs   125823.      448B     25.2
#>  8 fansi_vec_plain  39.03µs  40.89µs    24093.    5.02KB     21.7
#>  9 cli_txt_ansi      5.47µs   5.84µs   167186.        0B     33.4
#> 10 fansi_txt_ansi   30.85µs  32.65µs    30074.      688B     27.1
#> 11 cli_txt_plain     6.29µs   6.69µs   146840.        0B     29.4
#> 12 fansi_txt_plain  39.34µs  41.41µs    23532.    5.02KB     18.8

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          65.8µs   67.2µs    14724.    28.8KB     8.18
#> 2 fansi       122.4µs  125.1µs     7827.    55.3KB     8.22

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.72µs    7.3µs   134267.        0B    26.9 
#>  2 fansi_ansi        92.5µs  96.71µs    10158.   31.85KB    16.7 
#>  3 base_ansi       881.03ns 942.03ns   996797.        0B    99.7 
#>  4 cli_plain         6.33µs   7.17µs   131933.        0B    26.4 
#>  5 fansi_plain       92.1µs  96.24µs    10232.      688B    16.8 
#>  6 base_plain         812ns 862.05ns  1064963.        0B   107.  
#>  7 cli_vec_ansi     28.23µs   29.2µs    33976.      448B     6.80
#>  8 fansi_vec_ansi  112.72µs 116.66µs     8348.    5.02KB    14.7 
#>  9 base_vec_ansi    14.83µs  14.93µs    66548.      448B     0   
#> 10 cli_vec_plain    26.69µs  27.31µs    36263.      448B     7.25
#> 11 fansi_vec_plain 101.82µs 106.41µs     9201.    5.02KB    16.9 
#> 12 base_vec_plain    8.14µs   8.21µs   120698.      448B     0   
#> 13 cli_txt_ansi        28µs  28.85µs    34371.        0B     6.88
#> 14 fansi_txt_ansi  103.99µs 108.27µs     9100.      688B    16.7 
#> 15 base_txt_ansi     14.3µs  14.35µs    69311.        0B     0   
#> 16 cli_txt_plain    26.18µs  26.82µs    36906.        0B     7.38
#> 17 fansi_txt_plain   93.3µs  97.78µs     9967.      688B    16.6 
#> 18 base_txt_plain    8.43µs   8.95µs   112205.        0B    11.2
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.35µs   8.89µs   110786.        0B    33.2 
#>  2 fansi_ansi       91.67µs  95.32µs    10348.      688B    16.7 
#>  3 base_ansi         1.21µs   1.25µs   764617.        0B    76.5 
#>  4 cli_plain         8.35µs   8.92µs   110595.        0B    22.1 
#>  5 fansi_plain      91.67µs  95.27µs    10348.      688B    18.9 
#>  6 base_plain           1µs    1.1µs   762921.        0B     0   
#>  7 cli_vec_ansi     34.18µs  34.91µs    28420.      448B     8.53
#>  8 fansi_vec_ansi  120.03µs 123.98µs     7968.    5.02KB    14.6 
#>  9 base_vec_ansi     41.8µs  42.53µs    23358.      448B     0   
#> 10 cli_vec_plain    32.99µs  33.81µs    29036.      448B     5.81
#> 11 fansi_vec_plain 109.36µs 113.52µs     8629.    5.02KB    16.8 
#> 12 base_vec_plain   21.39µs  21.51µs    46233.      448B     0   
#> 13 cli_txt_ansi     34.37µs  35.12µs    28266.        0B     5.65
#> 14 fansi_txt_ansi  110.06µs 114.81µs     8592.      688B    16.7 
#> 15 base_txt_ansi    43.44µs  45.02µs    22136.        0B     0   
#> 16 cli_txt_plain    32.91µs  33.58µs    29507.        0B     8.85
#> 17 fansi_txt_plain  99.28µs 103.55µs     9514.      688B    16.7 
#> 18 base_txt_plain   23.84µs  24.11µs    41204.        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.69µs   7.23µs   134939.        0B    27.0 
#> 2 cli_plain       6.06µs   6.53µs   150234.        0B    30.1 
#> 3 cli_vec_ansi   40.22µs   41.1µs    24170.      848B     4.83
#> 4 cli_vec_plain  10.12µs  10.65µs    92567.      848B     9.26
#> 5 cli_txt_ansi   37.63µs   38.7µs    25333.        0B     5.07
#> 6 cli_txt_plain   7.04µs   7.54µs   130269.        0B    26.1

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.6µs   12.3µs    79654.        0B     31.9
#>  2 fansi_ansi        28.8µs   30.4µs    32255.      688B     25.8
#>  3 cli_plain         11.4µs   12.2µs    80303.        0B     32.1
#>  4 fansi_plain       28.3µs     30µs    32674.      688B     26.2
#>  5 cli_vec_ansi      20.5µs   21.5µs    45837.      848B     18.3
#>  6 fansi_vec_ansi    53.5µs     56µs    17516.    5.41KB     14.9
#>  7 cli_vec_plain       14µs     15µs    65459.      848B     19.6
#>  8 fansi_vec_plain   37.2µs   39.2µs    25052.    4.59KB     22.6
#>  9 cli_txt_ansi        20µs   20.8µs    47489.        0B     14.3
#> 10 fansi_txt_ansi    44.5µs   46.4µs    21214.    5.12KB     19.1
#> 11 cli_txt_plain     12.2µs     13µs    73443.        0B     22.0
#> 12 fansi_txt_plain   29.3µs   30.6µs    32132.      688B     25.7

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        146.91µs 151.95µs     6488.  103.29KB    18.9 
#>  2 fansi_ansi      124.86µs  130.7µs     7547.  102.13KB    23.5 
#>  3 base_ansi         4.11µs   4.42µs   221578.      224B    22.2 
#>  4 cli_plain       144.15µs 149.35µs     6554.    8.09KB    18.9 
#>  5 fansi_plain     124.97µs 130.11µs     7557.    9.62KB    23.5 
#>  6 base_plain        3.53µs   3.82µs   254622.        0B    25.5 
#>  7 cli_vec_ansi      7.26ms   7.42ms      134.  823.77KB    27.9 
#>  8 fansi_vec_ansi    1.02ms   1.06ms      918.  846.81KB    21.9 
#>  9 base_vec_ansi   154.82µs 160.01µs     6118.    22.7KB     2.03
#> 10 cli_vec_plain     7.24ms    7.4ms      135.  823.77KB    31.7 
#> 11 fansi_vec_plain 954.73µs      1ms      988.  845.98KB    20.0 
#> 12 base_vec_plain  109.72µs 114.43µs     8480.      848B     4.05
#> 13 cli_txt_ansi      3.25ms   3.31ms      301.    63.6KB     0   
#> 14 fansi_txt_ansi    1.54ms   1.56ms      637.   35.05KB     2.02
#> 15 base_txt_ansi   135.26µs 143.95µs     6842.   18.47KB     2.02
#> 16 cli_txt_plain     2.38ms    2.4ms      414.    63.6KB     0   
#> 17 fansi_txt_plain 509.56µs 544.78µs     1814.    30.6KB     2.02
#> 18 base_txt_plain   90.57µs  92.34µs    10551.   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         96.79µs 100.91µs     9786.   32.21KB    14.5 
#>  2 fansi_ansi       53.96µs  57.31µs    17214.   31.43KB    12.4 
#>  3 base_ansi         1.03µs   1.08µs   873064.     4.2KB    87.3 
#>  4 cli_plain        94.73µs  98.81µs    10001.        0B    12.4 
#>  5 fansi_plain      53.62µs   56.9µs    17357.      872B    14.6 
#>  6 base_plain      991.04ns   1.05µs   900103.        0B     0   
#>  7 cli_vec_ansi    233.71µs 239.05µs     4136.   16.73KB     6.15
#>  8 fansi_vec_ansi  124.76µs 128.74µs     7688.    5.59KB     8.26
#>  9 base_vec_ansi    35.29µs  35.57µs    27998.      848B     0   
#> 10 cli_vec_plain   178.69µs 183.15µs     5401.   16.73KB     8.29
#> 11 fansi_vec_plain 119.86µs 123.31µs     8032.    5.59KB     6.14
#> 12 base_vec_plain    30.8µs  30.99µs    32074.      848B     0   
#> 13 cli_txt_ansi    105.68µs 109.92µs     8981.        0B    12.4 
#> 14 fansi_txt_ansi   53.71µs  56.98µs    17266.      872B    14.6 
#> 15 base_txt_ansi     1.08µs   1.13µs   842238.        0B    84.2 
#> 16 cli_txt_plain    96.26µs 100.89µs     9774.        0B    12.5 
#> 17 fansi_txt_plain   53.5µs  56.57µs    17441.      872B    14.6 
#> 18 base_txt_plain    1.01µs   1.05µs   899640.        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         319.7µs 327.97µs    3007.   266.53KB    12.5 
#>  2 fansi_ansi        97.8µs 102.82µs    9577.    10.29KB    14.6 
#>  3 base_ansi        37.87µs   40.1µs   24517.         0B    12.3 
#>  4 cli_plain        197.4µs 203.47µs    4837.         0B    12.4 
#>  5 fansi_plain       96.7µs 102.15µs    9657.       872B    12.6 
#>  6 base_plain       31.33µs  32.99µs   29830.         0B    14.9 
#>  7 cli_vec_ansi     32.55ms   32.8ms      30.4    2.48KB    20.3 
#>  8 fansi_vec_ansi  242.05µs 247.52µs    4001.     7.25KB     6.14
#>  9 base_vec_ansi     2.16ms   2.24ms     446.    48.18KB    17.6 
#> 10 cli_vec_plain    19.83ms  20.02ms      49.8    2.48KB    15.7 
#> 11 fansi_vec_plain 202.82µs 206.69µs    4787.     6.42KB     8.23
#> 12 base_vec_plain    1.58ms   1.61ms     618.     47.4KB    14.9 
#> 13 cli_txt_ansi     22.88ms  22.98ms      43.3  507.59KB     7.22
#> 14 fansi_txt_ansi  229.17µs 234.69µs    4194.     6.77KB     6.12
#> 15 base_txt_ansi     2.03ms   2.06ms     475.   582.06KB     6.36
#> 16 cli_txt_plain     1.62ms   1.66ms     601.   369.84KB     8.58
#> 17 fansi_txt_plain 183.05µs  187.9µs    5227.     2.51KB     8.23
#> 18 base_txt_plain     1.3ms   1.33ms     745.   367.31KB     6.35

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.39µs   7.06µs   139062.    23.8KB    13.9 
#>  2 fansi_ansi       77.81µs  82.52µs    11867.   28.48KB    12.6 
#>  3 base_ansi            1µs   1.05µs   888625.        0B    88.9 
#>  4 cli_plain         6.33µs   6.87µs   142542.        0B    14.3 
#>  5 fansi_plain       77.8µs  81.95µs    11902.    1.98KB    12.5 
#>  6 base_plain       970.9ns   1.03µs   904821.        0B    90.5 
#>  7 cli_vec_ansi     26.85µs  27.77µs    35705.     1.7KB     3.57
#>  8 fansi_vec_ansi  114.35µs 118.28µs     8359.    8.86KB     8.30
#>  9 base_vec_ansi     5.87µs   6.07µs   161994.      848B    16.2 
#> 10 cli_vec_plain    22.58µs  23.77µs    41669.     1.7KB     4.17
#> 11 fansi_vec_plain 108.79µs 112.78µs     8747.    8.86KB    10.5 
#> 12 base_vec_plain    5.54µs   5.83µs   169700.      848B     0   
#> 13 cli_txt_ansi       6.2µs   6.88µs   136812.        0B    13.7 
#> 14 fansi_txt_ansi    77.8µs  82.07µs    12011.    1.98KB    14.6 
#> 15 base_txt_ansi     5.16µs   5.22µs   188577.        0B     0   
#> 16 cli_txt_plain     7.17µs   7.92µs   124027.        0B    12.4 
#> 17 fansi_txt_plain   77.7µs  82.29µs    11932.    1.98KB    14.8 
#> 18 base_txt_plain     3.4µs   3.44µs   285970.        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       106.31µs 110.39µs    8916.    11.85KB    10.3 
#>  2 base_ansi        1.35µs   1.39µs  701074.         0B     0   
#>  3 cli_plain       86.05µs   89.8µs   10983.     8.73KB     8.21
#>  4 base_plain       1.04µs   1.13µs  860897.         0B     0   
#>  5 cli_vec_ansi     3.96ms   4.08ms     245.   838.77KB    18.0 
#>  6 base_vec_ansi   78.39µs  78.84µs   12631.       848B     0   
#>  7 cli_vec_plain     2.2ms   2.27ms     439.    816.9KB    20.3 
#>  8 base_vec_plain  46.97µs  48.12µs   20708.       848B     0   
#>  9 cli_txt_ansi    12.82ms   12.9ms      77.5  114.42KB     4.19
#> 10 base_txt_ansi   77.67µs  78.95µs   12606.         0B     0   
#> 11 cli_txt_plain  251.56µs 255.71µs    3856.    18.16KB     2.01
#> 12 base_txt_plain  43.43µs  45.42µs   21971.         0B     2.20

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         73.1µs   75.7µs    12981.        0B    12.4 
#>  2 base_ansi        16.4µs   17.3µs    57079.        0B    17.1 
#>  3 cli_plain        72.2µs   75.5µs    13022.        0B    12.5 
#>  4 base_plain       16.4µs   17.4µs    56541.        0B    17.0 
#>  5 cli_vec_ansi    156.6µs  162.9µs     6076.     7.2KB     6.14
#>  6 base_vec_ansi    54.8µs     60µs    16504.    1.66KB     4.06
#>  7 cli_vec_plain     143µs  149.7µs     6606.     7.2KB     6.14
#>  8 base_vec_plain   47.6µs   53.5µs    18567.    1.66KB     4.06
#>  9 cli_txt_ansi    137.4µs  140.8µs     7015.        0B     8.19
#> 10 base_txt_ansi    38.1µs   39.2µs    25232.        0B     5.05
#> 11 cli_txt_plain   121.3µs  125.3µs     7887.        0B     8.17
#> 12 base_txt_plain     33µs   34.2µs    27044.        0B     5.41

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.12µs   8.77µs   111725.    12.3KB    11.2 
#> 2 base       871.02ns    912ns  1024192.        0B     0   
#> 3 cli_vec     24.36µs   25.2µs    39154.      448B     7.83
#> 4 base_vec    11.78µs  12.01µs    82776.      448B     0   
#> 5 cli_txt     24.94µs  25.77µs    38341.        0B     3.83
#> 6 base_txt    12.81µs  12.89µs    76845.        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.11µs   8.75µs   111775.        0B    11.2 
#> 2 base         1.27µs   1.32µs   720652.        0B     0   
#> 3 cli_vec     28.91µs  29.77µs    32634.      448B     3.26
#> 4 base_vec    45.44µs  46.95µs    21188.      448B     2.12
#> 5 cli_txt     30.13µs  30.93µs    31968.        0B     3.20
#> 6 base_txt    80.49µs  83.28µs    11861.        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          8.56µs   9.32µs   104883.        0B    21.0 
#> 2 base       871.02ns 912.11ns  1015326.        0B     0   
#> 3 cli_vec     19.72µs  20.65µs    47799.      448B     9.56
#> 4 base_vec    11.77µs  11.93µs    83061.      448B     0   
#> 5 cli_txt      20.5µs  21.41µs    46240.        0B     4.62
#> 6 base_txt    12.81µs  12.89µs    76748.        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          5.97µs   6.52µs   149655.    21.1KB    15.0 
#> 2 base         1.01µs   1.07µs   875577.        0B     0   
#> 3 cli_vec     29.48µs  30.32µs    32509.     1.7KB     6.50
#> 4 base_vec     7.66µs   7.89µs   125114.      848B     0   
#> 5 cli_txt         6µs   6.57µs   148683.        0B    14.9 
#> 6 base_txt     5.89µs   5.97µs   164743.        0B     0

Session info

sessioninfo::session_info()
#> ─ Session info ─────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.1 (2024-06-14)
#>  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-06-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.1.0   2024-05-16 [1] RSPM
#>  cli         * 3.6.3   2024-06-23 [1] local
#>  codetools     0.2-20  2024-03-31 [3] CRAN (R 4.4.1)
#>  desc          1.4.3   2023-12-10 [1] RSPM
#>  digest        0.6.35  2024-03-11 [1] RSPM
#>  evaluate      0.24.0  2024-06-10 [1] RSPM
#>  fansi       * 1.0.6   2023-12-08 [1] RSPM
#>  fastmap       1.2.0   2024-05-15 [1] RSPM
#>  fs            1.6.4   2024-04-25 [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.47    2024-05-29 [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.2   2024-05-15 [1] RSPM
#>  rlang         1.1.4   2024-06-04 [1] RSPM
#>  rmarkdown     2.27    2024-05-17 [1] RSPM
#>  sass          0.4.9   2024-03-15 [1] RSPM
#>  sessioninfo   1.2.2   2021-12-06 [1] any (@1.2.2)
#>  systemfonts   1.1.0   2024-05-15 [1] RSPM
#>  textshaping   0.4.0   2024-05-24 [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.45    2024-06-16 [1] RSPM
#>  yaml          2.3.8   2023-12-11 [1] RSPM
#> 
#>  [1] /home/runner/work/_temp/Library
#>  [2] /opt/R/4.4.1/lib/R/site-library
#>  [3] /opt/R/4.4.1/lib/R/library
#> 
#> ────────────────────────────────────────────────────────────────────────