Skip to content

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

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         59.3µs   64.4µs    15025.    97.7KB     17.2
#> 2 plain        59.2µs   63.9µs    15478.        0B     17.9
#> 3 base         17.1µs   18.4µs    53619.    48.4KB     16.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         62.5µs   67.3µs    14658.        0B     17.2
#> 2 plain        62.5µs     67µs    14734.        0B     19.7
#> 3 base         19.8µs   21.3µs    46320.        0B     18.5

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          173µs  181.7µs     5431.   75.06KB     10.5
#> 2 plain         132µs  140.6µs     7011.    8.73KB     10.5
#> 3 base            3µs    3.2µs   297959.        0B     29.8

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          478µs    500µs     1977.   33.19KB     15.0
#> 2 plain         479µs    500µs     1978.    1.09KB     15.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             8µs      9µs   109178.    8.02KB    21.8 
#>  2 fansi_ansi        41.6µs   45.4µs    21624.    4.18KB    19.7 
#>  3 cli_plain            8µs    8.9µs   109608.        0B    21.9 
#>  4 fansi_plain       41.5µs   45.2µs    21751.      688B    19.6 
#>  5 cli_vec_ansi      10.1µs   11.1µs    88057.      448B    17.6 
#>  6 fansi_vec_ansi      57µs   61.4µs    16010.    5.02KB    14.9 
#>  7 cli_vec_plain       11µs   11.5µs    85544.      448B     8.56
#>  8 fansi_vec_plain   53.8µs   55.7µs    17660.    5.02KB    17.4 
#>  9 cli_txt_ansi       7.9µs    8.3µs   118530.        0B    23.7 
#> 10 fansi_txt_ansi    41.1µs   42.5µs    23118.      688B    18.5 
#> 11 cli_txt_plain        9µs    9.4µs   103403.        0B    20.7 
#> 12 fansi_txt_plain   53.8µs   56.4µs    17407.    5.02KB    15.1

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          96.4µs   98.2µs    10104.    28.8KB     6.15
#> 2 fansi       185.2µs  190.1µs     5182.    55.4KB     6.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           9.8µs   10.4µs    93593.        0B    18.7 
#>  2 fansi_ansi       311.4µs  327.6µs     3027.   31.85KB    10.5 
#>  3 base_ansi          1.2µs    1.3µs   718119.        0B     0   
#>  4 cli_plain          9.7µs   10.3µs    94496.        0B    18.9 
#>  5 fansi_plain      314.3µs  326.9µs     3018.      688B    12.7 
#>  6 base_plain         1.1µs    1.2µs   824713.        0B     0   
#>  7 cli_vec_ansi      48.2µs   49.3µs    20104.      448B     4.08
#>  8 fansi_vec_ansi   357.8µs  369.9µs     2676.    5.02KB     8.32
#>  9 base_vec_ansi     20.2µs   20.6µs    47985.      448B     4.80
#> 10 cli_vec_plain     42.6µs   43.6µs    22763.      448B     4.55
#> 11 fansi_vec_plain  336.3µs  349.4µs     2830.    5.02KB     8.35
#> 12 base_vec_plain    11.5µs   11.7µs    84103.      448B     8.41
#> 13 cli_txt_ansi      48.9µs   50.1µs    19809.        0B     4.08
#> 14 fansi_txt_ansi   341.4µs  354.2µs     2798.      688B     8.29
#> 15 base_txt_ansi     19.5µs   20.7µs    48078.        0B     4.81
#> 16 cli_txt_plain     41.5µs   42.2µs    23477.        0B     4.70
#> 17 fansi_txt_plain    319µs  332.5µs     2978.      688B    10.5 
#> 18 base_txt_plain    11.2µs   11.7µs    85154.        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          12.1µs   12.8µs    76678.        0B    15.3 
#>  2 fansi_ansi       314.6µs  328.7µs     3014.      688B    10.5 
#>  3 base_ansi          1.7µs    1.8µs   525332.        0B    52.5 
#>  4 cli_plain         12.2µs   12.8µs    76184.        0B    15.2 
#>  5 fansi_plain      315.4µs  329.6µs     3005.      688B    10.5 
#>  6 base_plain         1.4µs    1.5µs   622241.        0B    62.2 
#>  7 cli_vec_ansi      58.5µs   59.7µs    16631.      448B     4.08
#>  8 fansi_vec_ansi   371.1µs  383.4µs     2582.    5.02KB     8.32
#>  9 base_vec_ansi     56.1µs   61.4µs    16215.      448B     0   
#> 10 cli_vec_plain     52.4µs   53.4µs    18554.      448B     6.18
#> 11 fansi_vec_plain  349.7µs  362.4µs     2729.    5.02KB     8.35
#> 12 base_vec_plain    29.8µs     31µs    32178.      448B     3.22
#> 13 cli_txt_ansi      59.2µs   60.7µs    16384.        0B     4.08
#> 14 fansi_txt_ansi   351.5µs  365.2µs     2711.      688B     8.29
#> 15 base_txt_ansi     62.1µs   64.1µs    15541.        0B     2.02
#> 16 cli_txt_plain     51.6µs   52.7µs    18823.        0B     4.07
#> 17 fansi_txt_plain  330.3µs  344.2µs     2877.      688B    10.5 
#> 18 base_txt_plain    32.1µs   33.3µs    29814.        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         9.9µs   10.5µs    93311.        0B     9.33
#> 2 cli_plain          9µs    9.5µs   103365.        0B    20.7 
#> 3 cli_vec_ansi    60.4µs   61.2µs    16257.      848B     4.08
#> 4 cli_vec_plain   15.4µs   16.1µs    61458.      848B     6.15
#> 5 cli_txt_ansi    58.7µs   59.6µs    16679.        0B     4.07
#> 6 cli_txt_plain   10.2µs   10.6µs    92969.        0B     9.30

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          16.1µs   16.8µs    58896.        0B    17.7 
#>  2 fansi_ansi        38.4µs   39.8µs    24594.      688B    22.2 
#>  3 cli_plain         16.2µs   16.9µs    57769.        0B    17.3 
#>  4 fansi_plain       37.8µs   39.6µs    24646.      688B    22.2 
#>  5 cli_vec_ansi      31.1µs   32.1µs    30720.      848B     9.22
#>  6 fansi_vec_ansi    82.1µs   84.9µs    11612.    5.41KB    10.6 
#>  7 cli_vec_plain     20.3µs   21.3µs    46128.      848B    18.5 
#>  8 fansi_vec_plain   52.8µs   55.2µs    17806.    4.59KB    15.0 
#>  9 cli_txt_ansi      29.3µs   30.3µs    32526.        0B     9.76
#> 10 fansi_txt_ansi    66.4µs   69.8µs    14123.    5.12KB    12.7 
#> 11 cli_txt_plain     17.2µs     18µs    54375.        0B    16.3 
#> 12 fansi_txt_plain   40.1µs   41.8µs    23303.      688B    21.0

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         247.6µs  258.5µs    3823.   103.35KB    12.7 
#>  2 fansi_ansi       184.8µs  196.7µs    5015.   102.16KB    15.1 
#>  3 base_ansi          7.8µs    8.5µs  116008.       224B     0   
#>  4 cli_plain       243.31µs  254.1µs    3879.     8.09KB    12.7 
#>  5 fansi_plain      180.4µs  192.8µs    5111.     9.62KB    15.0 
#>  6 base_plain         6.8µs    7.2µs  135758.         0B    13.6 
#>  7 cli_vec_ansi       9.8ms   9.97ms      99.5  823.77KB    21.0 
#>  8 fansi_vec_ansi    1.61ms   1.67ms     579.   846.81KB    13.3 
#>  9 base_vec_ansi   318.81µs 331.31µs    3006.     22.7KB     2.05
#> 10 cli_vec_plain     9.71ms   9.88ms     100.   823.77KB    21.2 
#> 11 fansi_vec_plain   1.51ms   1.55ms     643.   845.98KB    16.1 
#> 12 base_vec_plain   211.7µs  219.3µs    4546.       848B     2.02
#> 13 cli_txt_ansi      5.94ms   5.98ms     167.     63.6KB     0   
#> 14 fansi_txt_ansi    2.81ms   2.84ms     352.    35.05KB     2.03
#> 15 base_txt_ansi   286.91µs  296.5µs    3375.    18.47KB     0   
#> 16 cli_txt_plain     3.89ms   3.91ms     255.     63.6KB     0   
#> 17 fansi_txt_plain 898.52µs 938.32µs    1063.     30.6KB     4.10
#> 18 base_txt_plain   163.7µs  176.3µs    5662.    11.05KB     0

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         127.4µs  131.7µs     7467.   32.23KB    19.5 
#>  2 fansi_ansi        71.2µs   74.3µs    13170.   31.45KB    17.4 
#>  3 base_ansi          1.6µs    1.7µs   577688.     4.2KB    57.8 
#>  4 cli_plain        124.5µs  130.5µs     7569.        0B    17.1 
#>  5 fansi_plain       68.5µs   74.5µs    13186.      872B    19.5 
#>  6 base_plain         1.4µs    1.6µs   618846.        0B     0   
#>  7 cli_vec_ansi     356.3µs  366.5µs     2705.   16.73KB     8.30
#>  8 fansi_vec_ansi     175µs  180.6µs     5474.    5.59KB     8.34
#>  9 base_vec_ansi     57.3µs   57.9µs    17208.      848B     0   
#> 10 cli_vec_plain    267.2µs    277µs     3573.   16.73KB     8.40
#> 11 fansi_vec_plain  167.9µs  173.6µs     5537.    5.59KB     8.34
#> 12 base_vec_plain    46.3µs   47.4µs    20164.      848B     2.02
#> 13 cli_txt_ansi       141µs  148.9µs     6298.        0B    15.0 
#> 14 fansi_txt_ansi    71.3µs   75.3µs    12635.      872B    17.2 
#> 15 base_txt_ansi      1.6µs    1.7µs   546870.        0B    54.7 
#> 16 cli_txt_plain    126.8µs    132µs     7476.        0B    17.1 
#> 17 fansi_txt_plain   70.8µs   74.6µs    13162.      872B    19.5 
#> 18 base_txt_plain     1.5µs    1.6µs   621820.        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        522.41µs 543.01µs    1826.   266.69KB    15.1 
#>  2 fansi_ansi       130.1µs  138.9µs    6980.     10.3KB    17.2 
#>  3 base_ansi         52.8µs   54.8µs   17773.         0B    17.1 
#>  4 cli_plain       300.11µs 314.31µs    3132.         0B    12.7 
#>  5 fansi_plain      120.4µs  133.1µs    7399.       872B    17.2 
#>  6 base_plain        43.3µs   44.4µs   22273.         0B    17.8 
#>  7 cli_vec_ansi     52.78ms  52.78ms      18.8    2.48KB    37.7 
#>  8 fansi_vec_ansi  361.01µs 370.81µs    2668.     7.25KB     8.32
#>  9 base_vec_ansi     3.17ms   3.26ms     305.    48.18KB    20.8 
#> 10 cli_vec_plain    29.96ms  30.31ms      33.0    2.48KB    25.6 
#> 11 fansi_vec_plain 291.31µs 301.31µs    3273.     6.42KB     8.31
#> 12 base_vec_plain    2.31ms   2.39ms     415.     47.4KB    17.9 
#> 13 cli_txt_ansi     36.02ms  36.32ms      27.5  507.59KB    11.0 
#> 14 fansi_txt_ansi  332.41µs 343.51µs    2875.     6.77KB     8.30
#> 15 base_txt_ansi     5.06ms   5.16ms     193.   582.06KB     4.20
#> 16 cli_txt_plain     4.03ms   4.08ms     243.   369.84KB     6.39
#> 17 fansi_txt_plain 255.31µs 264.11µs    3737.     2.51KB     8.30
#> 18 base_txt_plain    2.94ms   2.99ms     332.   367.31KB     6.34

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           9.5µs   10.2µs    95604.   23.82KB    19.1 
#>  2 fansi_ansi       104.5µs  109.8µs     8910.   28.48KB    17.2 
#>  3 base_ansi          1.3µs    1.5µs   625860.        0B    62.6 
#>  4 cli_plain          9.4µs     10µs    97164.        0B    19.4 
#>  5 fansi_plain      103.6µs    109µs     8959.    1.98KB    17.2 
#>  6 base_plain         1.3µs    1.4µs   633746.        0B    63.4 
#>  7 cli_vec_ansi      43.4µs   44.9µs    22060.     1.7KB     4.41
#>  8 fansi_vec_ansi   161.1µs  167.9µs     5850.    8.86KB    10.6 
#>  9 base_vec_ansi     11.2µs   12.1µs    81911.      848B     8.19
#> 10 cli_vec_plain     36.2µs   37.6µs    26259.     1.7KB     5.25
#> 11 fansi_vec_plain  152.4µs    159µs     6166.    8.86KB    12.8 
#> 12 base_vec_plain    10.6µs   11.2µs    88910.      848B     0   
#> 13 cli_txt_ansi       9.5µs   10.2µs    94819.        0B    28.5 
#> 14 fansi_txt_ansi   104.2µs  109.7µs     8925.    1.98KB    17.2 
#> 15 base_txt_ansi      6.8µs    6.9µs   142253.        0B     0   
#> 16 cli_txt_plain     10.5µs   11.1µs    88048.        0B    17.6 
#> 17 fansi_txt_plain  102.9µs  106.1µs     9274.    1.98KB    19.3 
#> 18 base_txt_plain     4.5µs    4.6µs   215324.        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        157.9µs  164.8µs    5986.    11.85KB    12.7 
#>  2 base_ansi           2µs    2.1µs  462572.         0B     0   
#>  3 cli_plain       122.8µs  130.7µs    7491.     8.73KB    10.5 
#>  4 base_plain        1.5µs    1.6µs  591684.         0B    59.2 
#>  5 cli_vec_ansi     5.77ms   5.87ms     170.   838.77KB    21.8 
#>  6 base_vec_ansi   118.9µs  129.6µs    7706.       848B     0   
#>  7 cli_vec_plain     3.3ms   3.38ms     294.    816.9KB    23.6 
#>  8 base_vec_plain   76.3µs   77.3µs   12908.       848B     0   
#>  9 cli_txt_ansi    17.64ms  17.78ms      56.1  114.42KB     4.31
#> 10 base_txt_ansi   124.8µs  125.4µs    7954.         0B     0   
#> 11 cli_txt_plain  489.01µs 497.81µs    1991.    18.16KB     4.08
#> 12 base_txt_plain   74.5µs   74.9µs   13313.         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         97.7µs  102.4µs     9482.        0B    19.4 
#>  2 base_ansi        24.4µs   25.6µs    38121.        0B    15.3 
#>  3 cli_plain        97.7µs  101.7µs     9607.        0B    17.2 
#>  4 base_plain       24.2µs   25.4µs    38756.        0B    15.5 
#>  5 cli_vec_ansi    240.7µs  248.4µs     3955.     7.2KB     8.32
#>  6 base_vec_ansi   101.1µs  108.7µs     9141.    1.66KB     4.08
#>  7 cli_vec_plain   218.7µs  226.2µs     4380.     7.2KB     8.33
#>  8 base_vec_plain   86.5µs   93.3µs    10622.    1.66KB     4.08
#>  9 cli_txt_ansi      200µs  204.6µs     4834.        0B     8.28
#> 10 base_txt_ansi    68.8µs   70.3µs    14111.        0B     6.15
#> 11 cli_txt_plain   174.8µs  179.6µs     5501.        0B    10.4 
#> 12 base_txt_plain   56.5µs     58µs    17064.        0B     6.15

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            12µs   12.6µs    77406.    12.3KB    15.5 
#> 2 base          1.2µs    1.3µs   693100.        0B    69.3 
#> 3 cli_vec      40.3µs   41.6µs    23835.      448B     4.77
#> 4 base_vec     18.2µs   18.4µs    53957.      448B     0   
#> 5 cli_txt      40.1µs   41.5µs    23876.        0B     7.16
#> 6 base_txt     20.6µs   21.7µs    45355.        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          11.8µs   12.5µs    78480.        0B    15.7 
#> 2 base          1.8µs    1.9µs   495410.        0B     0   
#> 3 cli_vec      44.3µs     46µs    21543.      448B     6.46
#> 4 base_vec     73.5µs   74.2µs    13447.      448B     0   
#> 5 cli_txt      44.9µs   46.3µs    21404.        0B     4.28
#> 6 base_txt    136.2µs  137.9µs     7233.        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            13µs   13.8µs    70572.        0B    21.2 
#> 2 base          1.2µs    1.3µs   748455.        0B     0   
#> 3 cli_vec      30.3µs   31.4µs    31475.      448B     9.45
#> 4 base_vec     18.2µs   18.4µs    54092.      448B     0   
#> 5 cli_txt      33.2µs   34.4µs    28770.        0B     8.63
#> 6 base_txt     20.5µs   21.8µs    45688.        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           8.8µs    9.3µs   105614.    21.1KB    21.1 
#> 2 base          1.4µs    1.5µs   637438.        0B     0   
#> 3 cli_vec      45.8µs   46.9µs    21188.     1.7KB     6.36
#> 4 base_vec     12.9µs   13.2µs    75244.      848B     0   
#> 5 cli_txt       8.8µs    9.2µs   106441.        0B    31.9 
#> 6 base_txt     10.7µs     12µs    82791.        0B     0

Session info

sessioninfo::session_info()
#> ─ Session info ─────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.2.2 (2022-10-31)
#>  os       Ubuntu 22.04.1 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en
#>  collate  C.UTF-8
#>  ctype    C.UTF-8
#>  tz       UTC
#>  date     2023-01-09
#>  pandoc   2.19.2 @ /usr/bin/ (via rmarkdown)
#> 
#> ─ Packages ─────────────────────────────────────────────────────────────
#>  package     * version date (UTC) lib source
#>  bench         1.1.2   2021-11-30 [1] RSPM
#>  bslib         0.4.2   2022-12-16 [1] RSPM
#>  cachem        1.0.6   2021-08-19 [1] RSPM
#>  cli         * 3.6.0   2023-01-09 [1] local
#>  codetools     0.2-18  2020-11-04 [3] CRAN (R 4.2.2)
#>  desc          1.4.2   2022-09-08 [1] RSPM
#>  digest        0.6.31  2022-12-11 [1] RSPM
#>  evaluate      0.19    2022-12-13 [1] RSPM
#>  fansi       * 1.0.3   2022-03-24 [1] RSPM
#>  fastmap       1.1.0   2021-01-25 [1] RSPM
#>  fs            1.5.2   2021-12-08 [1] RSPM
#>  glue          1.6.2   2022-02-24 [1] RSPM
#>  htmltools     0.5.4   2022-12-07 [1] RSPM
#>  jquerylib     0.1.4   2021-04-26 [1] RSPM
#>  jsonlite      1.8.4   2022-12-06 [1] RSPM
#>  knitr         1.41    2022-11-18 [1] RSPM
#>  lifecycle     1.0.3   2022-10-07 [1] RSPM
#>  magrittr      2.0.3   2022-03-30 [1] RSPM
#>  memoise       2.0.1   2021-11-26 [1] RSPM
#>  pillar        1.8.1   2022-08-19 [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.0   2022-12-20 [1] RSPM
#>  R6            2.5.1   2021-08-19 [1] RSPM
#>  ragg          1.2.4   2022-10-24 [1] RSPM
#>  rlang         1.0.6   2022-09-24 [1] RSPM
#>  rmarkdown     2.19    2022-12-15 [1] RSPM
#>  rprojroot     2.0.3   2022-04-02 [1] RSPM
#>  sass          0.4.4   2022-11-24 [1] RSPM
#>  sessioninfo   1.2.2   2021-12-06 [1] RSPM
#>  stringi       1.7.8   2022-07-11 [1] RSPM
#>  stringr       1.5.0   2022-12-02 [1] RSPM
#>  systemfonts   1.0.4   2022-02-11 [1] RSPM
#>  textshaping   0.3.6   2021-10-13 [1] RSPM
#>  tibble        3.1.8   2022-07-22 [1] RSPM
#>  utf8          1.2.2   2021-07-24 [1] RSPM
#>  vctrs         0.5.1   2022-11-16 [1] RSPM
#>  xfun          0.36    2022-12-21 [1] RSPM
#>  yaml          2.3.6   2022-10-18 [1] RSPM
#> 
#>  [1] /home/runner/work/_temp/Library
#>  [2] /opt/R/4.2.2/lib/R/site-library
#>  [3] /opt/R/4.2.2/lib/R/library
#> 
#> ────────────────────────────────────────────────────────────────────────