Skip to content

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

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         43.9µs   46.4µs    21132.    98.5KB     23.3
#> 2 plain        44.6µs   46.9µs    21017.        0B     23.8
#> 3 base         11.5µs   12.4µs    79388.    48.4KB     23.8
bench::mark(
  ansi  = ansi_align(ansi, width = 20, align = "right"),
  plain = ansi_align(plain, width = 20, align = "right"), 
  base  = format(plain, width = 20, justify = "right"),
  check = FALSE
)
#> # A tibble: 3 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ansi         46.2µs   49.2µs    19951.        0B     25.4
#> 2 plain          46µs   48.4µs    20343.        0B     23.0
#> 3 base         13.5µs   14.5µs    67921.        0B     27.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        109.2µs 115.84µs     8476.   75.07KB     16.7
#> 2 plain        87.9µs  92.15µs    10695.    8.73KB     16.7
#> 3 base          1.9µs   2.03µs   480824.        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          320µs    338µs     2901.   33.17KB     23.4
#> 2 plain         321µs    332µs     2971.    1.09KB     21.0

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.51µs   6.02µs   162251.    8.02KB     32.5
#>  2 fansi_ansi        30.7µs  32.21µs    30504.    4.18KB     27.5
#>  3 cli_plain         5.54µs   5.83µs   169401.        0B     16.9
#>  4 fansi_plain      30.31µs  31.45µs    31352.      688B     28.2
#>  5 cli_vec_ansi      6.89µs   7.27µs   135401.      448B     27.1
#>  6 fansi_vec_ansi   39.69µs  41.25µs    23913.    5.02KB     21.5
#>  7 cli_vec_plain     7.52µs   7.86µs   125353.      448B     25.1
#>  8 fansi_vec_plain  38.54µs   40.2µs    24508.    5.02KB     22.1
#>  9 cli_txt_ansi      5.53µs   5.82µs   169080.        0B     33.8
#> 10 fansi_txt_ansi   30.43µs  31.67µs    31173.      688B     28.1
#> 11 cli_txt_plain     6.31µs   6.61µs   148909.        0B     14.9
#> 12 fansi_txt_plain   38.6µs  40.37µs    24442.    5.02KB     22.0

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.7µs   67.2µs    14779.    28.8KB     8.15
#> 2 fansi       122.7µs    125µs     7922.    55.3KB     8.17

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.5µs   6.97µs   140850.        0B    28.2 
#>  2 fansi_ansi       90.94µs  94.66µs    10375.   31.85KB    18.8 
#>  3 base_ansi       901.05ns 942.03ns  1033073.        0B     0   
#>  4 cli_plain         6.54µs   6.95µs   141455.        0B    28.3 
#>  5 fansi_plain      89.68µs  93.08µs    10599.      688B    18.8 
#>  6 base_plain      831.09ns 872.07ns  1103191.        0B     0   
#>  7 cli_vec_ansi     27.78µs  28.74µs    33468.      448B     6.70
#>  8 fansi_vec_ansi  110.53µs 113.93µs     8641.    5.02KB    16.7 
#>  9 base_vec_ansi    14.84µs  14.91µs    66108.      448B     0   
#> 10 cli_vec_plain    26.29µs   26.9µs    35880.      448B     7.18
#> 11 fansi_vec_plain 100.21µs 104.51µs     9443.    5.02KB    16.7 
#> 12 base_vec_plain    8.15µs   8.21µs   120248.      448B     0   
#> 13 cli_txt_ansi     27.75µs  28.62µs    33933.        0B     6.79
#> 14 fansi_txt_ansi  102.75µs 105.97µs     9320.      688B    16.6 
#> 15 base_txt_ansi    14.32µs  14.36µs    69167.        0B     0   
#> 16 cli_txt_plain    25.99µs  26.47µs    36717.        0B     7.34
#> 17 fansi_txt_plain     93µs  96.06µs    10283.      688B    18.9 
#> 18 base_txt_plain    8.92µs   8.97µs   110788.        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.14µs   8.65µs   113921.        0B    22.8 
#>  2 fansi_ansi        91.3µs  93.95µs    10503.      688B    18.8 
#>  3 base_ansi         1.24µs   1.27µs   762118.        0B     0   
#>  4 cli_plain         8.15µs   8.58µs   115179.        0B    34.6 
#>  5 fansi_plain      91.04µs  94.02µs    10393.      688B    18.8 
#>  6 base_plain        1.01µs   1.05µs   921207.        0B     0   
#>  7 cli_vec_ansi     33.91µs  34.47µs    28779.      448B     8.64
#>  8 fansi_vec_ansi  118.11µs 121.99µs     8081.    5.02KB    14.5 
#>  9 base_vec_ansi    41.79µs  42.52µs    23451.      448B     0   
#> 10 cli_vec_plain    33.02µs  33.61µs    29498.      448B     5.90
#> 11 fansi_vec_plain 107.95µs 111.84µs     8732.    5.02KB    16.7 
#> 12 base_vec_plain   21.42µs  21.58µs    46024.      448B     0   
#> 13 cli_txt_ansi     34.27µs  34.88µs    28421.        0B     8.53
#> 14 fansi_txt_ansi  110.46µs 113.86µs     8680.      688B    14.5 
#> 15 base_txt_ansi    43.87µs  45.05µs    21870.        0B     0   
#> 16 cli_txt_plain    32.65µs  33.27µs    29718.        0B     8.92
#> 17 fansi_txt_plain  99.16µs 102.29µs     9633.      688B    16.7 
#> 18 base_txt_plain   23.84µs  24.17µs    41126.        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.16µs   137281.        0B    13.7 
#> 2 cli_plain       6.05µs    6.4µs   153735.        0B    30.8 
#> 3 cli_vec_ansi   39.87µs  40.78µs    24226.      848B     4.85
#> 4 cli_vec_plain   9.93µs  10.49µs    93695.      848B    18.7 
#> 5 cli_txt_ansi   38.19µs  39.12µs    25392.        0B     2.54
#> 6 cli_txt_plain   6.86µs   7.25µs   135612.        0B    27.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.5µs   12.1µs    81229.        0B     24.4
#>  2 fansi_ansi        28.3µs   29.8µs    32985.      688B     29.7
#>  3 cli_plain         11.3µs   11.9µs    83084.        0B     24.9
#>  4 fansi_plain       27.5µs     29µs    33892.      688B     27.1
#>  5 cli_vec_ansi      20.2µs   20.9µs    46142.      848B     18.5
#>  6 fansi_vec_ansi      53µs   54.7µs    18038.    5.41KB     14.6
#>  7 cli_vec_plain       14µs   14.6µs    67344.      848B     26.9
#>  8 fansi_vec_plain   36.7µs   38.2µs    25795.    4.59KB     20.7
#>  9 cli_txt_ansi      19.7µs   20.5µs    48374.        0B     19.4
#> 10 fansi_txt_ansi    43.9µs   45.2µs    21884.    5.12KB     17.5
#> 11 cli_txt_plain     12.1µs   12.7µs    75143.        0B     30.1
#> 12 fansi_txt_plain     29µs   30.2µs    32663.      688B     26.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        145.15µs 149.12µs     6608.  103.31KB    20.9 
#>  2 fansi_ansi      125.58µs 129.68µs     7614.  102.13KB    23.2 
#>  3 base_ansi         4.09µs   4.47µs   219959.      224B    22.0 
#>  4 cli_plain       143.52µs 147.94µs     6603.    8.09KB    21.0 
#>  5 fansi_plain     122.68µs 127.34µs     7738.    9.62KB    23.3 
#>  6 base_plain        3.72µs    3.9µs   252902.        0B     0   
#>  7 cli_vec_ansi       7.2ms   7.32ms      136.  823.77KB    31.4 
#>  8 fansi_vec_ansi    1.02ms   1.06ms      924.  846.81KB    19.3 
#>  9 base_vec_ansi   155.57µs 163.15µs     6025.    22.7KB     4.13
#> 10 cli_vec_plain     7.16ms    7.3ms      136.  823.77KB    31.5 
#> 11 fansi_vec_plain 959.96µs 995.36µs      989.  845.98KB    21.6 
#> 12 base_vec_plain  110.14µs  114.2µs     8611.      848B     4.05
#> 13 cli_txt_ansi      3.27ms   3.37ms      293.    63.6KB     0   
#> 14 fansi_txt_ansi    1.52ms   1.55ms      643.   35.05KB     2.02
#> 15 base_txt_ansi   135.15µs 144.09µs     6927.   18.47KB     2.02
#> 16 cli_txt_plain     2.41ms   2.43ms      411.    63.6KB     0   
#> 17 fansi_txt_plain 506.44µs 535.34µs     1871.    30.6KB     6.15
#> 18 base_txt_plain    89.8µs  91.39µs    10803.   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         94.94µs  99.16µs     9912.   32.23KB     23.9
#>  2 fansi_ansi       53.12µs  55.24µs    17661.   31.43KB     27.4
#>  3 base_ansi         1.03µs   1.06µs   927028.     4.2KB      0  
#>  4 cli_plain        91.72µs  94.79µs    10419.        0B     25.4
#>  5 fansi_plain      52.71µs  54.83µs    17997.      872B     25.3
#>  6 base_plain      971.02ns   1.01µs   956099.        0B      0  
#>  7 cli_vec_ansi    229.99µs 235.04µs     4214.   16.73KB     10.3
#>  8 fansi_vec_ansi   122.3µs 125.14µs     7815.    5.59KB     14.5
#>  9 base_vec_ansi    35.28µs   35.7µs    27907.      848B      0  
#> 10 cli_vec_plain   174.83µs 179.54µs     5511.   16.73KB     12.5
#> 11 fansi_vec_plain 116.34µs 119.44µs     8270.    5.59KB     14.6
#> 12 base_vec_plain   30.78µs  30.94µs    32120.      848B      0  
#> 13 cli_txt_ansi    103.11µs 106.94µs     9242.        0B     23.1
#> 14 fansi_txt_ansi   52.39µs  54.96µs    17600.      872B     25.4
#> 15 base_txt_ansi     1.06µs    1.1µs   880040.        0B      0  
#> 16 cli_txt_plain    94.48µs  97.71µs    10097.        0B     25.3
#> 17 fansi_txt_plain  52.38µs  54.78µs    17800.      872B     25.3
#> 18 base_txt_plain       1µs   1.03µs   932078.        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        316.71µs 325.99µs    3000.   266.59KB    16.5 
#>  2 fansi_ansi       95.89µs 100.76µs    9828.    10.29KB    14.5 
#>  3 base_ansi        38.03µs  40.32µs   24444.         0B    12.2 
#>  4 cli_plain       197.77µs 203.62µs    4853.         0B    12.4 
#>  5 fansi_plain      95.78µs 100.25µs    9757.       872B    12.5 
#>  6 base_plain       31.71µs  33.51µs   28330.         0B    11.3 
#>  7 cli_vec_ansi     32.71ms  32.81ms      30.5    2.48KB    20.3 
#>  8 fansi_vec_ansi  238.66µs 245.28µs    4041.     7.25KB     8.20
#>  9 base_vec_ansi     2.16ms   2.22ms     448.    48.18KB    15.0 
#> 10 cli_vec_plain    19.96ms  20.09ms      49.7    2.48KB    15.7 
#> 11 fansi_vec_plain 200.69µs 206.09µs    4768.     6.42KB     8.23
#> 12 base_vec_plain    1.56ms   1.61ms     617.     47.4KB    14.9 
#> 13 cli_txt_ansi     22.68ms   22.9ms      43.3  507.59KB     6.84
#> 14 fansi_txt_ansi     229µs 233.46µs    4231.     6.77KB     6.11
#> 15 base_txt_ansi     2.03ms   2.07ms     476.   582.06KB     6.34
#> 16 cli_txt_plain     1.62ms   1.66ms     601.   369.84KB     8.56
#> 17 fansi_txt_plain 181.62µs 186.87µs    5298.     2.51KB     8.22
#> 18 base_txt_plain    1.29ms   1.33ms     749.   367.31KB     6.31

ansi_substr()

bench::mark(
  cli_ansi        = ansi_substr(ansi, 2, 10),
  fansi_ansi      = substr_sgr(ansi, 2, 10),
  base_ansi       = substr(ansi, 2, 10),
  cli_plain       = ansi_substr(plain, 2, 10),
  fansi_plain     = substr_sgr(plain, 2, 10),
  base_plain      = substr(plain, 2, 10),
  cli_vec_ansi    = ansi_substr(vec_ansi, 2, 10),
  fansi_vec_ansi  = substr_sgr(vec_ansi, 2, 10),
  base_vec_ansi   = substr(vec_ansi, 2, 10),
  cli_vec_plain   = ansi_substr(vec_plain, 2, 10),
  fansi_vec_plain = substr_sgr(vec_plain, 2, 10),
  base_vec_plain  = substr(vec_plain, 2, 10),
  cli_txt_ansi    = ansi_substr(txt_ansi, 2, 10),
  fansi_txt_ansi  = substr_sgr(txt_ansi, 2, 10),
  base_txt_ansi   = substr(txt_ansi, 2, 10),
  cli_txt_plain   = ansi_substr(txt_plain, 2, 10),
  fansi_txt_plain = substr_sgr(txt_plain, 2, 10),
  base_txt_plain  = substr(txt_plain, 2, 10),
  check = FALSE
)
#> # A tibble: 18 × 6
#>    expression           min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>      <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi          6.39µs   6.99µs   139936.   23.82KB    14.0 
#>  2 fansi_ansi       77.53µs  81.38µs    12104.   28.48KB    12.5 
#>  3 base_ansi         1.02µs   1.08µs   864966.        0B    86.5 
#>  4 cli_plain         6.33µs    6.9µs   142418.        0B    14.2 
#>  5 fansi_plain      77.08µs  81.08µs    12056.    1.98KB    12.4 
#>  6 base_plain           1µs   1.05µs   895057.        0B    89.5 
#>  7 cli_vec_ansi     27.18µs  27.95µs    35488.     1.7KB     3.55
#>  8 fansi_vec_ansi   113.7µs    118µs     8380.    8.86KB     8.35
#>  9 base_vec_ansi     5.79µs   6.12µs   160369.      848B    16.0 
#> 10 cli_vec_plain    22.68µs  23.61µs    41939.     1.7KB     4.19
#> 11 fansi_vec_plain 108.08µs 112.34µs     8792.    8.86KB    10.4 
#> 12 base_vec_plain    5.51µs    5.8µs   171138.      848B     0   
#> 13 cli_txt_ansi      6.45µs   7.04µs   139194.        0B    13.9 
#> 14 fansi_txt_ansi   77.55µs  81.23µs    12149.    1.98KB    14.6 
#> 15 base_txt_ansi      5.2µs   5.25µs   188763.        0B     0   
#> 16 cli_txt_plain     7.19µs    7.8µs   125655.        0B    12.6 
#> 17 fansi_txt_plain  75.99µs   80.3µs    12317.    1.98KB    14.4 
#> 18 base_txt_plain    3.42µs   3.46µs   285666.        0B     0

ansi_tolower() , ansi_toupper()

bench::mark(
  cli_ansi        = ansi_tolower(ansi),
  base_ansi       = tolower(ansi),
  cli_plain       = ansi_tolower(plain),
  base_plain      = tolower(plain),
  cli_vec_ansi    = ansi_tolower(vec_ansi),
  base_vec_ansi   = tolower(vec_ansi),
  cli_vec_plain   = ansi_tolower(vec_plain),
  base_vec_plain  = tolower(vec_plain),
  cli_txt_ansi    = ansi_tolower(txt_ansi),
  base_txt_ansi   = tolower(txt_ansi),
  cli_txt_plain   = ansi_tolower(txt_plain),
  base_txt_plain  = tolower(txt_plain),
  check = FALSE
)
#> # A tibble: 12 × 6
#>    expression          min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>     <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 cli_ansi       104.98µs 108.46µs    9019.    11.88KB     8.16
#>  2 base_ansi        1.35µs   1.39µs  706311.         0B    70.6 
#>  3 cli_plain       85.07µs  87.95µs   11231.     8.73KB     8.18
#>  4 base_plain       1.04µs   1.07µs  916605.         0B     0   
#>  5 cli_vec_ansi     3.85ms   3.93ms     253.   838.77KB    17.9 
#>  6 base_vec_ansi    78.1µs  78.82µs   12638.       848B     0   
#>  7 cli_vec_plain     2.2ms   2.25ms     435.    816.9KB    17.6 
#>  8 base_vec_plain  47.12µs  48.21µs   20674.       848B     0   
#>  9 cli_txt_ansi    12.83ms  12.92ms      77.4  114.42KB     4.18
#> 10 base_txt_ansi   78.77µs  79.23µs   12566.         0B     0   
#> 11 cli_txt_plain  252.54µs 257.85µs    3773.    18.16KB     4.05
#> 12 base_txt_plain  44.44µs   45.4µs   21883.         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           73µs   77.2µs    12093.        0B    12.4 
#>  2 base_ansi        16.2µs   17.3µs    55426.        0B    16.6 
#>  3 cli_plain        71.8µs   75.5µs    13070.        0B    12.4 
#>  4 base_plain       16.2µs   17.3µs    56829.        0B    17.1 
#>  5 cli_vec_ansi    157.2µs  161.5µs     6114.     7.2KB     6.13
#>  6 base_vec_ansi    54.8µs   58.7µs    16707.    1.66KB     4.04
#>  7 cli_vec_plain   143.7µs  148.7µs     6611.     7.2KB     6.13
#>  8 base_vec_plain   46.8µs     52µs    18984.    1.66KB     4.05
#>  9 cli_txt_ansi    137.2µs  141.7µs     6965.        0B     6.14
#> 10 base_txt_ansi    37.6µs   38.6µs    25192.        0B     7.56
#> 11 cli_txt_plain   121.7µs  124.6µs     7936.        0B     8.16
#> 12 base_txt_plain   33.3µs   34.2µs    28879.        0B     5.78

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          7.97µs   8.63µs   113438.    12.3KB    22.7 
#> 2 base       901.05ns 942.03ns  1006627.        0B     0   
#> 3 cli_vec     24.31µs  25.09µs    38108.      448B     3.81
#> 4 base_vec    11.79µs  11.94µs    83000.      448B     0   
#> 5 cli_txt     24.95µs  25.67µs    37608.        0B     7.52
#> 6 base_txt    12.83µs  12.91µs    76814.        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          7.99µs   8.63µs   114029.        0B    11.4 
#> 2 base         1.29µs   1.35µs   712933.        0B    71.3 
#> 3 cli_vec     28.81µs  29.55µs    33586.      448B     3.36
#> 4 base_vec    45.63µs  47.14µs    21029.      448B     0   
#> 5 cli_txt     30.08µs  30.89µs    32125.        0B     3.21
#> 6 base_txt    80.35µs  82.11µs    12097.        0B     2.01
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.67µs   9.37µs   104915.        0B    10.5 
#> 2 base       891.04ns 982.08ns   982101.        0B     0   
#> 3 cli_vec     19.73µs   20.6µs    48058.      448B     9.61
#> 4 base_vec    11.79µs   11.9µs    83339.      448B     0   
#> 5 cli_txt     20.55µs  21.23µs    46428.        0B     9.29
#> 6 base_txt    12.83µs  12.89µs    76932.        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.53µs   149720.    21.1KB    15.0 
#> 2 base         1.04µs   1.09µs   871905.        0B    87.2 
#> 3 cli_vec     29.36µs  30.08µs    33005.     1.7KB     3.30
#> 4 base_vec     7.71µs   7.96µs   124615.      848B     0   
#> 5 cli_txt      5.93µs   6.52µs   149480.        0B    29.9 
#> 6 base_txt     5.92µs   5.97µs   165829.        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.9000 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
#> 
#> ────────────────────────────────────────────────────────────────────────