Skip to content

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

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µs     50µs    19619.    97.8KB     21.3
#> 2 plain          47µs   50.2µs    19550.        0B     22.2
#> 3 base         12.3µs   13.4µs    73089.    48.4KB     21.9
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         49.2µs   52.1µs    18844.        0B     23.9
#> 2 plain          48µs   51.6µs    19002.        0B     25.9
#> 3 base         14.5µs   15.8µs    62116.        0B     24.9

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.35µs 117.53µs     8299.   75.12KB     16.9
#> 2 plain       88.78µs  93.28µs    10549.    8.73KB     16.9
#> 3 base         1.87µs   2.01µs   474035.        0B     47.4

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          354µs    369µs     2679.    33.2KB     21.6
#> 2 plain         354µs    369µs     2682.    1.09KB     21.5

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.74µs   6.22µs   149729.    8.03KB     30.0
#>  2 fansi_ansi       31.51µs  34.71µs    27851.    4.18KB     22.3
#>  3 cli_plain         5.73µs    6.1µs   160088.        0B     16.0
#>  4 fansi_plain      31.74µs  33.53µs    29233.      688B     14.6
#>  5 cli_vec_ansi      6.97µs   7.45µs   130478.      448B     26.1
#>  6 fansi_vec_ansi   41.08µs  43.29µs    22568.    5.02KB     11.3
#>  7 cli_vec_plain     7.57µs      8µs   123010.      448B     12.3
#>  8 fansi_vec_plain  39.63µs  41.99µs    23265.    5.02KB     11.6
#>  9 cli_txt_ansi      5.64µs   6.07µs   160762.        0B     16.1
#> 10 fansi_txt_ansi    31.6µs  33.89µs    28454.      688B     14.2
#> 11 cli_txt_plain     6.48µs    6.9µs   142436.        0B     14.2
#> 12 fansi_txt_plain  40.17µs  42.36µs    23262.    5.02KB     11.6

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          57.6µs   59.2µs    16728.    28.8KB     6.13
#> 2 fansi       123.8µs  126.8µs     7685.    55.4KB     6.13

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          7.09µs   7.69µs   127779.        0B    12.8 
#>  2 fansi_ansi       93.31µs  97.45µs    10077.   31.85KB    10.4 
#>  3 base_ansi        841.1ns 882.08ns  1066278.        0B     0   
#>  4 cli_plain         7.13µs   7.72µs   127407.        0B    12.7 
#>  5 fansi_plain      92.68µs  97.19µs    10094.      688B    10.3 
#>  6 base_plain      791.04ns 832.02ns  1119103.        0B     0   
#>  7 cli_vec_ansi      28.9µs  29.71µs    33287.      448B     3.33
#>  8 fansi_vec_ansi  113.59µs 117.67µs     8356.    5.02KB     8.26
#>  9 base_vec_ansi     12.2µs  12.29µs    80394.      448B     8.04
#> 10 cli_vec_plain     27.6µs   28.7µs    34596.      448B     3.46
#> 11 fansi_vec_plain  103.7µs 107.61µs     9052.    5.02KB     8.27
#> 12 base_vec_plain    7.31µs   7.35µs   134486.      448B     0   
#> 13 cli_txt_ansi     28.97µs  29.61µs    33465.        0B     3.35
#> 14 fansi_txt_ansi  104.42µs 109.57µs     8906.      688B    10.3 
#> 15 base_txt_ansi     11.6µs  11.65µs    85004.        0B     0   
#> 16 cli_txt_plain    27.18µs  27.85µs    35035.        0B     3.50
#> 17 fansi_txt_plain  94.44µs  99.42µs     9906.      688B    10.3 
#> 18 base_txt_plain    6.92µs   6.97µs   141860.        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          8.81µs    9.5µs   103149.        0B    20.6 
#>  2 fansi_ansi       92.51µs  97.06µs    10147.      688B    10.4 
#>  3 base_ansi         1.17µs   1.21µs   780111.        0B     0   
#>  4 cli_plain         8.94µs   9.68µs   101599.        0B    10.2 
#>  5 fansi_plain      92.68µs  97.37µs    10030.      688B    10.3 
#>  6 base_plain      991.98ns   1.07µs   877669.        0B    87.8 
#>  7 cli_vec_ansi     34.24µs  35.02µs    28301.      448B     2.83
#>  8 fansi_vec_ansi  119.77µs 124.18µs     7945.    5.02KB     8.28
#>  9 base_vec_ansi     35.6µs  35.81µs    27767.      448B     0   
#> 10 cli_vec_plain    33.27µs  34.13µs    29032.      448B     2.90
#> 11 fansi_vec_plain 110.63µs 114.24µs     8614.    5.02KB    10.4 
#> 12 base_vec_plain    18.5µs  18.79µs    53027.      448B     0   
#> 13 cli_txt_ansi     34.61µs  35.38µs    27692.        0B     2.77
#> 14 fansi_txt_ansi  110.52µs 115.47µs     8541.      688B     8.22
#> 15 base_txt_ansi    37.97µs  38.22µs    25901.        0B     2.59
#> 16 cli_txt_plain    32.88µs  33.63µs    29480.        0B     2.95
#> 17 fansi_txt_plain 101.34µs 106.07µs     9262.      688B    10.4 
#> 18 base_txt_plain   20.42µs  20.66µs    47139.        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           7µs   7.64µs   128416.        0B    12.8 
#> 2 cli_plain       6.54µs   7.09µs   138344.        0B    13.8 
#> 3 cli_vec_ansi   33.12µs  34.08µs    29132.      848B     2.91
#> 4 cli_vec_plain   10.5µs  11.16µs    88341.      848B     8.84
#> 5 cli_txt_ansi   32.45µs  33.26µs    29845.        0B     2.98
#> 6 cli_txt_plain   7.41µs   8.01µs   122710.        0B    12.3

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.5µs    61764.        0B    12.4 
#>  2 fansi_ansi        29.6µs   31.7µs    30660.      688B    15.3 
#>  3 cli_plain         11.6µs   12.3µs    79897.        0B    16.0 
#>  4 fansi_plain       28.8µs   30.3µs    32483.      688B    16.2 
#>  5 cli_vec_ansi      20.3µs   21.1µs    46814.      848B     9.36
#>  6 fansi_vec_ansi    55.4µs   57.6µs    17177.    5.41KB     8.32
#>  7 cli_vec_plain     14.2µs     15µs    65827.      848B    13.2 
#>  8 fansi_vec_plain   37.5µs   39.5µs    24716.    4.59KB    12.4 
#>  9 cli_txt_ansi        20µs   20.7µs    47928.        0B     9.59
#> 10 fansi_txt_ansi    45.5µs   47.8µs    18782.    5.12KB     8.33
#> 11 cli_txt_plain     12.2µs     13µs    75096.        0B    15.0 
#> 12 fansi_txt_plain   30.3µs   31.9µs    30468.      688B    15.2

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        149.28µs 155.49µs     6299.  103.37KB    12.5 
#>  2 fansi_ansi      132.53µs 139.42µs     7081.  102.16KB    12.6 
#>  3 base_ansi         4.09µs   4.49µs   219492.      224B     0   
#>  4 cli_plain       147.22µs 152.98µs     6407.    8.09KB    12.5 
#>  5 fansi_plain     129.64µs 137.76µs     7159.    9.62KB    10.4 
#>  6 base_plain        3.55µs   3.97µs   229837.        0B    23.0 
#>  7 cli_vec_ansi      7.49ms   7.63ms      131.  823.77KB    13.8 
#>  8 fansi_vec_ansi    1.09ms   1.14ms      849.  846.81KB    17.9 
#>  9 base_vec_ansi   154.95µs 159.97µs     6148.    22.7KB     2.04
#> 10 cli_vec_plain     7.35ms   7.54ms      132.  823.77KB    13.9 
#> 11 fansi_vec_plain   1.02ms   1.07ms      923.  845.98KB    17.8 
#> 12 base_vec_plain  107.99µs 110.95µs     8846.      848B     4.07
#> 13 cli_txt_ansi      3.32ms   3.38ms      296.    63.6KB     0   
#> 14 fansi_txt_ansi    1.55ms   1.57ms      622.   35.05KB     2.03
#> 15 base_txt_ansi   142.92µs 151.04µs     6624.   18.47KB     2.02
#> 16 cli_txt_plain     2.48ms   2.51ms      397.    63.6KB     0   
#> 17 fansi_txt_plain 516.51µs 533.89µs     1865.    30.6KB     2.02
#> 18 base_txt_plain   91.51µs  94.36µs    10412.   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        100.22µs 104.52µs     9345.   32.25KB    12.5 
#>  2 fansi_ansi       55.14µs  58.72µs    16596.   31.45KB    14.7 
#>  3 base_ansi         1.05µs   1.09µs   869888.     4.2KB     0   
#>  4 cli_plain        98.17µs 102.71µs     9553.        0B    12.7 
#>  5 fansi_plain       54.6µs  58.38µs    16657.      872B    14.7 
#>  6 base_plain           1µs   1.04µs   921381.        0B     0   
#>  7 cli_vec_ansi    225.14µs  231.9µs     4262.   16.73KB     6.19
#>  8 fansi_vec_ansi  124.58µs 128.38µs     7669.    5.59KB     6.17
#>  9 base_vec_ansi    34.14µs  34.54µs    28787.      848B     0   
#> 10 cli_vec_plain    182.3µs 188.64µs     5169.   16.73KB     8.96
#> 11 fansi_vec_plain 120.08µs 122.81µs     8049.    5.59KB     6.17
#> 12 base_vec_plain   29.37µs  29.93µs    33137.      848B     0   
#> 13 cli_txt_ansi    107.49µs 111.34µs     8660.        0B    12.5 
#> 14 fansi_txt_ansi   54.35µs  56.84µs    17156.      872B    14.7 
#> 15 base_txt_ansi     1.11µs   1.14µs   846757.        0B     0   
#> 16 cli_txt_plain    98.98µs 102.65µs     9576.        0B    12.5 
#> 17 fansi_txt_plain  54.83µs  58.03µs    16942.      872B    14.7 
#> 18 base_txt_plain    1.02µs   1.06µs   909127.        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        337.65µs 349.37µs    2797.   266.74KB    12.5 
#>  2 fansi_ansi       99.58µs 105.09µs    9349.     10.3KB    12.6 
#>  3 base_ansi        40.63µs  42.66µs   22942.         0B    11.5 
#>  4 cli_plain       208.14µs 216.34µs    4537.         0B    10.3 
#>  5 fansi_plain      98.14µs  103.7µs    9344.       872B    14.7 
#>  6 base_plain       33.04µs  35.09µs   27931.         0B    11.2 
#>  7 cli_vec_ansi     34.79ms  35.05ms      28.4    2.48KB    21.3 
#>  8 fansi_vec_ansi  241.42µs 248.21µs    3977.     7.25KB     6.15
#>  9 base_vec_ansi      2.3ms   2.36ms     417.    48.18KB    15.2 
#> 10 cli_vec_plain    21.13ms  21.34ms      46.7    2.48KB    16.5 
#> 11 fansi_vec_plain 205.21µs  210.4µs    4682.     6.42KB     6.16
#> 12 base_vec_plain    1.68ms   1.71ms     579.     47.4KB    15.1 
#> 13 cli_txt_ansi     21.37ms  21.63ms      45.7  507.59KB     6.85
#> 14 fansi_txt_ansi  231.13µs 235.97µs    4178.     6.77KB     6.14
#> 15 base_txt_ansi      2.1ms   2.15ms     455.   582.06KB     8.75
#> 16 cli_txt_plain     1.68ms   1.72ms     578.   369.84KB     6.38
#> 17 fansi_txt_plain  184.3µs 190.58µs    5116.     2.51KB     8.30
#> 18 base_txt_plain    1.35ms   1.38ms     717.   367.31KB     6.36

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.38µs    7.1µs   134301.   23.84KB    13.4 
#>  2 fansi_ansi       79.54µs  83.47µs    11730.   28.48KB    12.6 
#>  3 base_ansi       972.07ns   1.03µs   906168.        0B     0   
#>  4 cli_plain         6.31µs   6.83µs   142312.        0B    28.5 
#>  5 fansi_plain      77.58µs  80.56µs    12067.    1.98KB    12.6 
#>  6 base_plain      971.02ns   1.02µs   933407.        0B     0   
#>  7 cli_vec_ansi     27.08µs  28.25µs    35067.     1.7KB     7.01
#>  8 fansi_vec_ansi  113.87µs 117.68µs     8341.    8.86KB     8.35
#>  9 base_vec_ansi     5.83µs   6.55µs   150291.      848B     0   
#> 10 cli_vec_plain    22.69µs  23.53µs    42014.     1.7KB     8.40
#> 11 fansi_vec_plain 107.63µs 111.11µs     8759.    8.86KB     8.35
#> 12 base_vec_plain    5.44µs   6.21µs   140491.      848B     0   
#> 13 cli_txt_ansi      6.41µs   7.05µs   121476.        0B    24.3 
#> 14 fansi_txt_ansi   79.04µs  83.17µs    11831.    1.98KB    12.5 
#> 15 base_txt_ansi     3.85µs    3.9µs   251108.        0B     0   
#> 16 cli_txt_plain      7.3µs      8µs   116513.        0B    11.7 
#> 17 fansi_txt_plain  78.33µs   82.6µs    11938.    1.98KB    14.7 
#> 18 base_txt_plain    2.63µs   2.69µs   363041.        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       105.12µs 109.94µs    8960.    11.87KB    10.4 
#>  2 base_ansi        1.31µs   1.42µs  695769.         0B     0   
#>  3 cli_plain       84.62µs  88.39µs   11137.     8.73KB    10.4 
#>  4 base_plain       1.01µs   1.05µs  911748.         0B     0   
#>  5 cli_vec_ansi     4.06ms   4.21ms     235.   838.77KB    18.1 
#>  6 base_vec_ansi   72.79µs  74.29µs   13416.       848B     0   
#>  7 cli_vec_plain    2.25ms   2.32ms     430.    816.9KB    17.5 
#>  8 base_vec_plain  43.47µs  44.26µs   22494.       848B     0   
#>  9 cli_txt_ansi    11.29ms  11.45ms      86.3  114.42KB     4.21
#> 10 base_txt_ansi   73.27µs  75.16µs   13295.         0B     0   
#> 11 cli_txt_plain  244.54µs  250.4µs    3918.    18.16KB     4.06
#> 12 base_txt_plain  41.53µs  41.72µs   23734.         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.5µs    12380.        0B    14.7 
#>  2 base_ansi        17.5µs   18.5µs    53072.        0B    10.6 
#>  3 cli_plain        75.3µs   79.1µs    12331.        0B    12.5 
#>  4 base_plain       17.7µs   18.7µs    52847.        0B    15.9 
#>  5 cli_vec_ansi    155.5µs  162.6µs     6071.     7.2KB     6.17
#>  6 base_vec_ansi    53.5µs   59.1µs    16784.    1.66KB     4.07
#>  7 cli_vec_plain   144.1µs  150.1µs     6505.     7.2KB     6.17
#>  8 base_vec_plain     49µs   54.4µs    18222.    1.66KB     4.07
#>  9 cli_txt_ansi    132.4µs  136.1µs     7250.        0B     8.22
#> 10 base_txt_ansi      36µs   37.1µs    26647.        0B     5.33
#> 11 cli_txt_plain   117.6µs  121.4µs     8110.        0B     8.21
#> 12 base_txt_plain   32.4µs   33.8µs    29175.        0B     8.76

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.67µs   9.31µs   105089.    12.3KB    21.0 
#> 2 base       851.11ns 892.09ns  1062796.        0B     0   
#> 3 cli_vec     25.67µs  26.55µs    37294.      448B     3.73
#> 4 base_vec    11.41µs  11.58µs    85662.      448B     0   
#> 5 cli_txt      26.6µs  27.52µs    36033.        0B     7.21
#> 6 base_txt    12.54µs  12.62µs    78560.        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.63µs    9.3µs   105772.        0B    10.6 
#> 2 base         1.25µs    1.3µs   723665.        0B    72.4 
#> 3 cli_vec     29.91µs     31µs    31908.      448B     3.19
#> 4 base_vec    44.38µs   45.2µs    21911.      448B     0   
#> 5 cli_txt     30.79µs   31.8µs    29891.        0B     5.98
#> 6 base_txt    81.02µs   82.9µs    11967.        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.33µs   10.1µs    96726.        0B     9.67
#> 2 base       860.89ns  900.9ns  1024266.        0B   102.  
#> 3 cli_vec     20.15µs     21µs    46171.      448B     4.62
#> 4 base_vec    11.42µs   11.6µs    85524.      448B     0   
#> 5 cli_txt     21.17µs     22µs    44834.        0B     8.97
#> 6 base_txt    12.55µs   12.6µs    78243.        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.21µs    6.9µs   140381.    21.1KB    28.1 
#> 2 base         1.01µs   1.07µs   870110.        0B     0   
#> 3 cli_vec     30.79µs  31.75µs    31125.     1.7KB     3.11
#> 4 base_vec     7.75µs   7.96µs   123738.      848B    12.4 
#> 5 cli_txt      6.09µs   6.78µs   144194.        0B    14.4 
#> 6 base_txt     5.45µs    5.5µs   178169.        0B     0

Session info

sessioninfo::session_info()
#> ─ Session info ─────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.3.2 (2023-10-31)
#>  os       Ubuntu 22.04.3 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en
#>  collate  C.UTF-8
#>  ctype    C.UTF-8
#>  tz       UTC
#>  date     2023-11-14
#>  pandoc   2.19.2 @ /usr/bin/ (via rmarkdown)
#> 
#> ─ Packages ─────────────────────────────────────────────────────────────
#>  package     * version    date (UTC) lib source
#>  bench         1.1.3      2023-05-04 [1] RSPM
#>  bslib         0.5.1      2023-08-11 [1] RSPM
#>  cachem        1.0.8      2023-05-01 [1] RSPM
#>  cli         * 3.6.1.9000 2023-11-14 [1] local
#>  codetools     0.2-19     2023-02-01 [3] CRAN (R 4.3.2)
#>  desc          1.4.2      2022-09-08 [1] RSPM
#>  digest        0.6.33     2023-07-07 [1] RSPM
#>  evaluate      0.23       2023-11-01 [1] RSPM
#>  fansi       * 1.0.5      2023-10-08 [1] RSPM
#>  fastmap       1.1.1      2023-02-24 [1] RSPM
#>  fs            1.6.3      2023-07-20 [1] RSPM
#>  glue          1.6.2      2022-02-24 [1] RSPM
#>  htmltools     0.5.7      2023-11-03 [1] RSPM
#>  jquerylib     0.1.4      2021-04-26 [1] RSPM
#>  jsonlite      1.8.7      2023-06-29 [1] RSPM
#>  knitr         1.45       2023-10-30 [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.7      2022-12-14 [1] any (@2.0.7)
#>  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.2.6      2023-10-10 [1] RSPM
#>  rlang         1.1.2      2023-11-04 [1] RSPM
#>  rmarkdown     2.25       2023-09-18 [1] RSPM
#>  rprojroot     2.0.4      2023-11-05 [1] RSPM
#>  sass          0.4.7      2023-07-15 [1] RSPM
#>  sessioninfo   1.2.2      2021-12-06 [1] RSPM
#>  stringi       1.7.12     2023-01-11 [1] RSPM
#>  stringr       1.5.0      2022-12-02 [1] RSPM
#>  systemfonts   1.0.5      2023-10-09 [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.4      2023-10-12 [1] RSPM
#>  xfun          0.41       2023-11-01 [1] RSPM
#>  yaml          2.3.7      2023-01-23 [1] RSPM
#> 
#>  [1] /home/runner/work/_temp/Library
#>  [2] /opt/R/4.3.2/lib/R/site-library
#>  [3] /opt/R/4.3.2/lib/R/library
#> 
#> ────────────────────────────────────────────────────────────────────────