ANSI function benchmarks
Gábor Csárdi
2025-04-29
Source:vignettes/ansi-benchmark.Rmd
ansi-benchmark.Rmd
$output function (x, options) { if (class == “output” && output_asis(x, options)) return(x) hook.t(x, options[[paste0(“attr.”, class)]], options[[paste0(“class.”, class)]]) } <bytecode: 0x556c5d494780> <environment: 0x556c5def23b0>
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.
ansi <- format_inline(
"{col_green(symbol$tick)} {.code print(x)} {.emph emphasised}"
)
plain <- ansi_strip(ansi)
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 46.1µs 49.8µs 19526. 99.3KB 18.9
#> 2 plain 46.3µs 49.9µs 19557. 0B 19.4
#> 3 base 11.3µs 12.5µs 77942. 48.4KB 15.6
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 48.2µs 52µs 18730. 0B 21.1
#> 2 plain 47.9µs 51.3µs 18937. 0B 21.2
#> 3 base 13.3µs 14.3µs 68127. 0B 20.4
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 112.9µs 119.35µs 8173. 75.07KB 16.8
#> 2 plain 89.2µs 94.22µs 10285. 8.73KB 12.4
#> 3 base 1.9µs 2.03µs 474480. 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 340µs 363µs 2727. 33.17KB 19.1
#> 2 plain 342µs 364µs 2714. 1.09KB 19.1
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.95µs 6.5µs 148698. 9.2KB 29.7
#> 2 fansi_ansi 30.89µs 33.59µs 28794. 4.18KB 23.1
#> 3 cli_plain 5.91µs 6.36µs 152801. 0B 30.6
#> 4 fansi_plain 30.2µs 32.75µs 29857. 688B 23.9
#> 5 cli_vec_ansi 7.23µs 7.68µs 127459. 448B 25.5
#> 6 fansi_vec_ansi 39.09µs 40.97µs 23698. 5.02KB 19.0
#> 7 cli_vec_plain 7.92µs 8.33µs 116928. 448B 23.4
#> 8 fansi_vec_plain 37.96µs 39.82µs 24501. 5.02KB 19.6
#> 9 cli_txt_ansi 5.78µs 6.25µs 155952. 0B 31.2
#> 10 fansi_txt_ansi 30.39µs 31.97µs 30537. 688B 24.4
#> 11 cli_txt_plain 6.75µs 7.11µs 136738. 0B 27.4
#> 12 fansi_txt_plain 37.86µs 39.69µs 24592. 5.02KB 19.7
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 59µs 60.4µs 15886. 22.7KB 8.17
#> 2 fansi 116µs 118.3µs 8301. 55.3KB 10.3
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.67µs 7.21µs 132919. 0B 26.6
#> 2 fansi_ansi 92.27µs 96.67µs 10077. 38.83KB 16.7
#> 3 base_ansi 911.07ns 952.04ns 997869. 0B 0
#> 4 cli_plain 6.8µs 7.31µs 133299. 0B 26.7
#> 5 fansi_plain 91.69µs 95.84µs 10078. 688B 16.7
#> 6 base_plain 831.09ns 872.07ns 1090322. 0B 0
#> 7 cli_vec_ansi 28.57µs 29.33µs 33542. 448B 6.71
#> 8 fansi_vec_ansi 112.54µs 116.78µs 8321. 5.02KB 12.5
#> 9 base_vec_ansi 16.03µs 16.09µs 60781. 448B 0
#> 10 cli_vec_plain 26.72µs 27.37µs 35931. 448B 7.19
#> 11 fansi_vec_plain 102.24µs 106.89µs 9119. 5.02KB 14.6
#> 12 base_vec_plain 9.55µs 9.62µs 102174. 448B 10.2
#> 13 cli_txt_ansi 27.96µs 28.7µs 34326. 0B 3.43
#> 14 fansi_txt_ansi 104.2µs 108.56µs 8888. 688B 14.5
#> 15 base_txt_ansi 15.65µs 15.7µs 62868. 0B 6.29
#> 16 cli_txt_plain 26.2µs 26.83µs 36616. 0B 3.66
#> 17 fansi_txt_plain 93.23µs 98.43µs 9906. 688B 16.7
#> 18 base_txt_plain 9.2µs 9.25µs 106643. 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.38µs 9.01µs 108066. 0B 21.6
#> 2 fansi_ansi 93.27µs 97.34µs 10007. 688B 16.7
#> 3 base_ansi 1.23µs 1.28µs 745904. 0B 0
#> 4 cli_plain 8.25µs 8.9µs 107138. 0B 32.2
#> 5 fansi_plain 92.59µs 96.98µs 10043. 688B 16.7
#> 6 base_plain 1.01µs 1.06µs 911836. 0B 0
#> 7 cli_vec_ansi 34.88µs 35.61µs 27657. 448B 5.53
#> 8 fansi_vec_ansi 120.04µs 124.59µs 7826. 5.02KB 12.5
#> 9 base_vec_ansi 41.42µs 41.73µs 23733. 448B 0
#> 10 cli_vec_plain 33.29µs 33.93µs 28973. 448B 8.69
#> 11 fansi_vec_plain 109.54µs 114.07µs 8552. 5.02KB 12.4
#> 12 base_vec_plain 21.58µs 21.89µs 44559. 448B 4.46
#> 13 cli_txt_ansi 34.78µs 35.48µs 27709. 0B 5.54
#> 14 fansi_txt_ansi 112.12µs 116.47µs 8372. 688B 14.5
#> 15 base_txt_ansi 43.86µs 44.45µs 22256. 0B 0
#> 16 cli_txt_plain 32.89µs 33.52µs 29388. 0B 5.88
#> 17 fansi_txt_plain 100.82µs 105.34µs 9266. 688B 14.5
#> 18 base_txt_plain 23.09µs 23.84µs 41480. 0B 4.15
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.82µs 7.31µs 133678. 0B 26.7
#> 2 cli_plain 6.35µs 6.8µs 143791. 0B 14.4
#> 3 cli_vec_ansi 33.64µs 34.52µs 28351. 848B 5.67
#> 4 cli_vec_plain 10.24µs 10.83µs 90259. 848B 18.1
#> 5 cli_txt_ansi 32.79µs 33.8µs 28990. 0B 2.90
#> 6 cli_txt_plain 7.19µs 7.64µs 127629. 0B 25.5
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 26.2µs 27.5µs 35348. 0B 28.3
#> 2 fansi_ansi 28.2µs 29.8µs 32640. 7.24KB 26.1
#> 3 cli_plain 25.6µs 27µs 36205. 0B 29.0
#> 4 fansi_plain 27.6µs 29.2µs 33336. 688B 26.7
#> 5 cli_vec_ansi 35.1µs 36.7µs 26524. 848B 18.6
#> 6 fansi_vec_ansi 53.6µs 55.5µs 17639. 5.41KB 14.7
#> 7 cli_vec_plain 28.8µs 30.3µs 32182. 848B 25.8
#> 8 fansi_vec_plain 36.6µs 38.7µs 25171. 4.59KB 20.2
#> 9 cli_txt_ansi 34.8µs 36.8µs 26535. 0B 21.2
#> 10 fansi_txt_ansi 44.8µs 46.5µs 21007. 5.12KB 16.6
#> 11 cli_txt_plain 26.8µs 28.2µs 34587. 0B 24.2
#> 12 fansi_txt_plain 28.8µs 30.5µs 31348. 688B 25.1
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 166.12µs 174.72µs 5541. 104.34KB 19.1
#> 2 fansi_ansi 127.72µs 134.59µs 7211. 106.35KB 19.1
#> 3 base_ansi 4.2µs 4.55µs 214611. 224B 21.5
#> 4 cli_plain 164.95µs 172.27µs 5654. 8.09KB 19.0
#> 5 fansi_plain 126.45µs 132.22µs 7354. 9.62KB 19.1
#> 6 base_plain 3.68µs 3.95µs 246360. 0B 24.6
#> 7 cli_vec_ansi 7.56ms 7.74ms 129. 823.77KB 25.3
#> 8 fansi_vec_ansi 1.05ms 1.09ms 891. 846.81KB 17.4
#> 9 base_vec_ansi 157.37µs 163.64µs 5974. 22.7KB 4.11
#> 10 cli_vec_plain 7.47ms 7.62ms 131. 823.77KB 25.1
#> 11 fansi_vec_plain 990.83µs 1.03ms 952. 845.98KB 19.8
#> 12 base_vec_plain 106.96µs 112.02µs 8703. 848B 4.05
#> 13 cli_txt_ansi 3.43ms 3.47ms 288. 63.6KB 0
#> 14 fansi_txt_ansi 1.55ms 1.58ms 632. 35.05KB 2.02
#> 15 base_txt_ansi 137.85µs 146.3µs 6778. 18.47KB 2.02
#> 16 cli_txt_plain 2.37ms 2.41ms 414. 63.6KB 0
#> 17 fansi_txt_plain 519.69µs 535.79µs 1851. 30.6KB 6.17
#> 18 base_txt_plain 87.86µs 90.69µs 10768. 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 149.71µs 158.04µs 6155. 33.84KB 23.6
#> 2 fansi_ansi 54.8µs 57.93µs 16711. 31.43KB 23.2
#> 3 base_ansi 1.05µs 1.12µs 848618. 4.2KB 0
#> 4 cli_plain 146.5µs 152.4µs 6418. 0B 24.1
#> 5 fansi_plain 54.41µs 57µs 17090. 872B 21.1
#> 6 base_plain 1µs 1.04µs 912149. 0B 91.2
#> 7 cli_vec_ansi 274.18µs 284.95µs 3457. 16.73KB 12.6
#> 8 fansi_vec_ansi 122.59µs 126.57µs 7734. 5.59KB 10.3
#> 9 base_vec_ansi 35.99µs 36.37µs 27232. 848B 0
#> 10 cli_vec_plain 229.28µs 238.16µs 4113. 16.73KB 16.9
#> 11 fansi_vec_plain 119.08µs 123.34µs 7943. 5.59KB 10.3
#> 12 base_vec_plain 30.08µs 30.54µs 32285. 848B 3.23
#> 13 cli_txt_ansi 156.32µs 163.16µs 5973. 0B 21.0
#> 14 fansi_txt_ansi 54.51µs 57.73µs 16904. 872B 23.4
#> 15 base_txt_ansi 1.12µs 1.16µs 837015. 0B 0
#> 16 cli_txt_plain 146.18µs 152.05µs 6437. 0B 23.1
#> 17 fansi_txt_plain 54µs 57.66µs 16885. 872B 23.3
#> 18 base_txt_plain 1.02µs 1.06µs 908614. 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 400.9µs 423.16µs 2343. 0B 21.2
#> 2 fansi_ansi 97.31µs 102.5µs 9474. 97.33KB 21.3
#> 3 base_ansi 38.58µs 40.91µs 23111. 0B 20.8
#> 4 cli_plain 270.48µs 281.74µs 3486. 0B 19.2
#> 5 fansi_plain 94.55µs 99.93µs 9745. 872B 21.1
#> 6 base_plain 32.18µs 33.6µs 28979. 0B 20.3
#> 7 cli_vec_ansi 41.78ms 41.78ms 23.9 2.48KB 263.
#> 8 fansi_vec_ansi 244.45µs 252.26µs 3912. 7.25KB 10.3
#> 9 base_vec_ansi 2.23ms 2.29ms 432. 48.18KB 24.5
#> 10 cli_vec_plain 28.79ms 28.87ms 34.5 2.48KB 49.3
#> 11 fansi_vec_plain 203.21µs 210.49µs 4620. 6.42KB 12.5
#> 12 base_vec_plain 1.63ms 1.68ms 592. 47.4KB 22.0
#> 13 cli_txt_ansi 24.01ms 24.5ms 40.9 507.59KB 13.6
#> 14 fansi_txt_ansi 233.88µs 242.38µs 4061. 6.77KB 10.3
#> 15 base_txt_ansi 1.25ms 1.28ms 763. 582.06KB 18.1
#> 16 cli_txt_plain 1.27ms 1.3ms 749. 369.84KB 17.9
#> 17 fansi_txt_plain 184.72µs 191.93µs 5084. 2.51KB 12.5
#> 18 base_txt_plain 854.05µs 883.33µs 1090. 367.31KB 17.9
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.73µs 7.51µs 126308. 24.83KB 25.3
#> 2 fansi_ansi 77.8µs 82.81µs 11742. 28.48KB 21.6
#> 3 base_ansi 1.03µs 1.08µs 890795. 0B 0
#> 4 cli_plain 6.86µs 7.35µs 133007. 0B 26.6
#> 5 fansi_plain 76.79µs 80.65µs 12020. 1.98KB 21.2
#> 6 base_plain 962.06ns 1.04µs 909218. 0B 0
#> 7 cli_vec_ansi 27.18µs 28.1µs 35058. 1.7KB 10.5
#> 8 fansi_vec_ansi 113.44µs 117.98µs 8274. 8.86KB 14.8
#> 9 base_vec_ansi 5.95µs 6.12µs 159279. 848B 0
#> 10 cli_vec_plain 23.14µs 24.09µs 40811. 1.7KB 8.16
#> 11 fansi_vec_plain 109.1µs 113.6µs 8578. 8.86KB 14.8
#> 12 base_vec_plain 5.74µs 5.88µs 158542. 848B 15.9
#> 13 cli_txt_ansi 6.92µs 7.5µs 130189. 0B 26.0
#> 14 fansi_txt_ansi 78.65µs 82.29µs 11789. 1.98KB 21.2
#> 15 base_txt_ansi 5.2µs 5.25µs 186429. 0B 0
#> 16 cli_txt_plain 7.65µs 8.36µs 116680. 0B 23.3
#> 17 fansi_txt_plain 77.88µs 82.04µs 11912. 1.98KB 21.2
#> 18 base_txt_plain 3.42µs 3.48µs 280490. 0B 28.1
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 108.04µs 112.77µs 8586. 11.88KB 14.7
#> 2 base_ansi 1.34µs 1.37µs 699487. 0B 0
#> 3 cli_plain 85.59µs 89.4µs 10869. 8.73KB 16.8
#> 4 base_plain 1.02µs 1.06µs 914029. 0B 0
#> 5 cli_vec_ansi 4.08ms 4.19ms 237. 838.77KB 28.7
#> 6 base_vec_ansi 74.19µs 74.64µs 13265. 848B 0
#> 7 cli_vec_plain 2.31ms 2.36ms 419. 816.9KB 27.5
#> 8 base_vec_plain 43.94µs 44.66µs 22188. 848B 0
#> 9 cli_txt_ansi 13.55ms 13.66ms 73.2 114.42KB 6.66
#> 10 base_txt_ansi 74.93µs 76.27µs 12989. 0B 0
#> 11 cli_txt_plain 270.8µs 278.86µs 3521. 18.16KB 6.12
#> 12 base_txt_plain 41.55µs 42.93µs 23100. 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 109µs 114.7µs 8467. 0B 23.5
#> 2 base_ansi 16.2µs 17.2µs 56451. 0B 22.6
#> 3 cli_plain 108.2µs 113.5µs 8566. 0B 21.7
#> 4 base_plain 16.1µs 16.9µs 57400. 0B 23.0
#> 5 cli_vec_ansi 200.1µs 210µs 4680. 7.2KB 12.4
#> 6 base_vec_ansi 55.7µs 63µs 15618. 1.66KB 6.08
#> 7 cli_vec_plain 186.3µs 196.6µs 5000. 7.2KB 12.4
#> 8 base_vec_plain 49.5µs 57.1µs 17206. 1.66KB 6.14
#> 9 cli_txt_ansi 177.3µs 182.7µs 5368. 0B 14.5
#> 10 base_txt_ansi 38.3µs 39.4µs 24904. 0B 7.47
#> 11 cli_txt_plain 160.1µs 165.5µs 5927. 0B 16.6
#> 12 base_txt_plain 33.9µs 34.9µs 27969. 0B 11.2
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.16µs 8.68µs 112420. 0B 22.5
#> 2 base 901.05ns 952.04ns 992857. 0B 0
#> 3 cli_vec 23.14µs 23.77µs 41352. 448B 12.4
#> 4 base_vec 11.57µs 11.87µs 83350. 448B 0
#> 5 cli_txt 23.27µs 23.93µs 41031. 0B 8.21
#> 6 base_txt 12.41µs 12.72µs 77727. 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.12µs 8.63µs 113156. 0B 22.6
#> 2 base 1.33µs 1.38µs 691122. 0B 0
#> 3 cli_vec 28.58µs 29.3µs 33578. 448B 6.72
#> 4 base_vec 51.19µs 51.73µs 18978. 448B 2.01
#> 5 cli_txt 28.93µs 29.61µs 33222. 0B 6.65
#> 6 base_txt 87.24µs 87.93µs 11268. 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.63µs 9.18µs 106313. 0B 31.9
#> 2 base 862.17ns 942.03ns 1006026. 0B 0
#> 3 cli_vec 19.58µs 20.35µs 48243. 448B 14.5
#> 4 base_vec 11.6µs 11.83µs 83465. 448B 0
#> 5 cli_txt 20.19µs 20.94µs 46867. 0B 9.38
#> 6 base_txt 12.42µs 12.72µs 77884. 0B 7.79
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.47µs 6.97µs 139681. 22.1KB 27.9
#> 2 base 1.07µs 1.11µs 844423. 0B 84.5
#> 3 cli_vec 29.2µs 29.96µs 32806. 1.7KB 6.56
#> 4 base_vec 7.88µs 8.28µs 119035. 848B 0
#> 5 cli_txt 6.4µs 6.99µs 138737. 0B 41.6
#> 6 base_txt 5.46µs 5.53µs 177410. 0B 0
Session info
sessioninfo::session_info()
#> ─ Session info ──────────────────────────────────────────────────────
#> setting value
#> version R version 4.5.0 (2025-04-11)
#> os Ubuntu 24.04.2 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language en
#> collate C.UTF-8
#> ctype C.UTF-8
#> tz UTC
#> date 2025-04-29
#> pandoc 3.1.11 @ /opt/hostedtoolcache/pandoc/3.1.11/x64/ (via rmarkdown)
#> quarto NA
#>
#> ─ Packages ──────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> bench 1.1.4 2025-01-16 [1] RSPM
#> bslib 0.9.0 2025-01-30 [1] RSPM
#> cachem 1.1.0 2024-05-16 [1] RSPM
#> cli * 3.6.5.9000 2025-04-29 [1] local
#> codetools 0.2-20 2024-03-31 [3] CRAN (R 4.5.0)
#> desc 1.4.3 2023-12-10 [1] RSPM
#> digest 0.6.37 2024-08-19 [1] RSPM
#> evaluate 1.0.3 2025-01-10 [1] RSPM
#> fansi * 1.0.6 2023-12-08 [1] RSPM
#> fastmap 1.2.0 2024-05-15 [1] RSPM
#> fs 1.6.6 2025-04-12 [1] RSPM
#> glue 1.8.0 2024-09-30 [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 2.0.0 2025-03-27 [1] RSPM
#> knitr 1.50 2025-03-16 [1] RSPM
#> lifecycle 1.0.4 2023-11-07 [1] RSPM
#> magrittr 2.0.3 2022-03-30 [1] RSPM
#> pillar 1.10.2 2025-04-05 [1] RSPM
#> pkgconfig 2.0.3 2019-09-22 [1] RSPM
#> pkgdown 2.1.2 2025-04-28 [1] any (@2.1.2)
#> profmem 0.6.0 2020-12-13 [1] RSPM
#> R6 2.6.1 2025-02-15 [1] RSPM
#> ragg 1.4.0 2025-04-10 [1] RSPM
#> rlang 1.1.6 2025-04-11 [1] RSPM
#> rmarkdown 2.29 2024-11-04 [1] RSPM
#> sass 0.4.10 2025-04-11 [1] RSPM
#> sessioninfo 1.2.3 2025-02-05 [1] any (@1.2.3)
#> systemfonts 1.2.2 2025-04-04 [1] RSPM
#> textshaping 1.0.0 2025-01-20 [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.52 2025-04-02 [1] RSPM
#> yaml 2.3.10 2024-07-26 [1] RSPM
#>
#> [1] /home/runner/work/_temp/Library
#> [2] /opt/R/4.5.0/lib/R/site-library
#> [3] /opt/R/4.5.0/lib/R/library
#> * ── Packages attached to the search path.
#>
#> ─────────────────────────────────────────────────────────────────────