ANSI function benchmarks
Gábor Csárdi
2025-04-24
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: 0x55c051f9b950> <environment: 0x55c0529c9150>
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.4µs 49.7µs 19608. 99.2KB 19.0
#> 2 plain 45.6µs 49.3µs 19708. 0B 17.5
#> 3 base 11.5µs 12.6µs 76884. 48.4KB 23.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 48.2µs 51.8µs 18653. 0B 21.2
#> 2 plain 48.1µs 51.6µs 18847. 0B 21.4
#> 3 base 13.4µs 15µs 64761. 0B 25.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 112.81µs 121.39µs 8038. 75.01KB 14.7
#> 2 plain 89.68µs 95.09µs 10226. 8.73KB 14.7
#> 3 base 1.87µs 2.02µs 476753. 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 342µs 363µs 2697. 33.15KB 19.3
#> 2 plain 339µs 363µs 2704. 1.09KB 19.4
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.86µs 6.39µs 150786. 9.19KB 30.2
#> 2 fansi_ansi 30.34µs 33.47µs 29008. 4.18KB 23.2
#> 3 cli_plain 5.85µs 6.37µs 151689. 0B 30.3
#> 4 fansi_plain 29.62µs 33.06µs 29409. 688B 23.5
#> 5 cli_vec_ansi 7.09µs 7.73µs 126203. 448B 25.2
#> 6 fansi_vec_ansi 38.69µs 41.01µs 23681. 5.02KB 19.0
#> 7 cli_vec_plain 7.71µs 8.3µs 103528. 448B 20.7
#> 8 fansi_vec_plain 37.47µs 39.36µs 24527. 5.02KB 19.6
#> 9 cli_txt_ansi 5.66µs 6.19µs 154759. 0B 31.0
#> 10 fansi_txt_ansi 29.94µs 31.81µs 30568. 688B 24.5
#> 11 cli_txt_plain 6.51µs 7µs 139393. 0B 27.9
#> 12 fansi_txt_plain 37.42µs 39.64µs 24527. 5.02KB 19.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 59.1µs 61µs 16102. 22.6KB 8.18
#> 2 fansi 115.5µs 119µs 8239. 55.3KB 8.20
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.89µs 7.49µs 129566. 0B 25.9
#> 2 fansi_ansi 92.22µs 97.19µs 9949. 38.83KB 14.6
#> 3 base_ansi 880.91ns 922.01ns 996638. 0B 99.7
#> 4 cli_plain 6.76µs 7.5µs 129572. 0B 25.9
#> 5 fansi_plain 91.2µs 96.82µs 9999. 688B 14.7
#> 6 base_plain 791.04ns 871.02ns 1039007. 0B 104.
#> 7 cli_vec_ansi 28.5µs 29.6µs 33004. 448B 3.30
#> 8 fansi_vec_ansi 112.89µs 117.98µs 8248. 5.02KB 14.8
#> 9 base_vec_ansi 15.97µs 16.08µs 61080. 448B 0
#> 10 cli_vec_plain 26.67µs 27.59µs 35453. 448B 7.09
#> 11 fansi_vec_plain 102.47µs 108.06µs 8979. 5.02KB 14.8
#> 12 base_vec_plain 9.53µs 9.61µs 102155. 448B 0
#> 13 cli_txt_ansi 27.94µs 28.83µs 34052. 0B 6.81
#> 14 fansi_txt_ansi 104.5µs 109.67µs 8869. 688B 14.6
#> 15 base_txt_ansi 15.62µs 15.68µs 62807. 0B 0
#> 16 cli_txt_plain 26.19µs 26.93µs 36403. 0B 7.28
#> 17 fansi_txt_plain 94.05µs 99.48µs 9763. 688B 14.6
#> 18 base_txt_plain 9.13µs 9.66µs 102398. 0B 10.2
bench::mark(
cli_ansi = ansi_nchar(ansi, type = "width"),
fansi_ansi = nchar_sgr(ansi, type = "width"),
base_ansi = nchar(ansi, "width"),
cli_plain = ansi_nchar(plain, type = "width"),
fansi_plain = nchar_sgr(plain, type = "width"),
base_plain = nchar(plain, "width"),
cli_vec_ansi = ansi_nchar(vec_ansi, type = "width"),
fansi_vec_ansi = nchar_sgr(vec_ansi, type = "width"),
base_vec_ansi = nchar(vec_ansi, "width"),
cli_vec_plain = ansi_nchar(vec_plain, type = "width"),
fansi_vec_plain = nchar_sgr(vec_plain, type = "width"),
base_vec_plain = nchar(vec_plain, "width"),
cli_txt_ansi = ansi_nchar(txt_ansi, type = "width"),
fansi_txt_ansi = nchar_sgr(txt_ansi, type = "width"),
base_txt_ansi = nchar(txt_ansi, "width"),
cli_txt_plain = ansi_nchar(txt_plain, type = "width"),
fansi_txt_plain = nchar_sgr(txt_plain, type = "width"),
base_txt_plain = nchar(txt_plain, type = "width"),
check = FALSE
)
#> # A tibble: 18 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 cli_ansi 8.5µs 9.2µs 104988. 0B 21.0
#> 2 fansi_ansi 92.56µs 97.62µs 9904. 688B 16.8
#> 3 base_ansi 1.2µs 1.24µs 743720. 0B 0
#> 4 cli_plain 8.46µs 9.25µs 104892. 0B 31.5
#> 5 fansi_plain 92.71µs 97.58µs 9941. 688B 16.6
#> 6 base_plain 1µs 1.04µs 907399. 0B 0
#> 7 cli_vec_ansi 34.79µs 35.75µs 27416. 448B 5.48
#> 8 fansi_vec_ansi 119.81µs 125µs 7759. 5.02KB 12.5
#> 9 base_vec_ansi 41.39µs 41.67µs 23738. 448B 0
#> 10 cli_vec_plain 33.46µs 34.33µs 28596. 448B 8.58
#> 11 fansi_vec_plain 110.88µs 115.35µs 8432. 5.02KB 12.6
#> 12 base_vec_plain 21.62µs 21.92µs 44982. 448B 4.50
#> 13 cli_txt_ansi 34.69µs 35.52µs 27535. 0B 5.51
#> 14 fansi_txt_ansi 111.47µs 116.78µs 8335. 688B 12.5
#> 15 base_txt_ansi 44.12µs 44.34µs 22269. 0B 2.23
#> 16 cli_txt_plain 32.96µs 33.71µs 29125. 0B 5.83
#> 17 fansi_txt_plain 101.84µs 106.88µs 9115. 688B 14.6
#> 18 base_txt_plain 23.18µs 23.84µs 40611. 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.79µs 7.43µs 130250. 0B 13.0
#> 2 cli_plain 6.39µs 7.01µs 138874. 0B 27.8
#> 3 cli_vec_ansi 33.42µs 34.57µs 28429. 848B 5.69
#> 4 cli_vec_plain 10.3µs 10.96µs 89111. 848B 8.91
#> 5 cli_txt_ansi 32.83µs 33.86µs 28898. 0B 5.78
#> 6 cli_txt_plain 7.21µs 7.8µs 125015. 0B 12.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.8µs 34915. 0B 28.0
#> 2 fansi_ansi 27.8µs 29.8µs 32255. 7.24KB 22.6
#> 3 cli_plain 26µs 27.8µs 34950. 0B 28.0
#> 4 fansi_plain 27.5µs 29.3µs 33130. 688B 26.5
#> 5 cli_vec_ansi 35.3µs 37µs 26282. 848B 21.0
#> 6 fansi_vec_ansi 53.4µs 56µs 17428. 5.41KB 12.6
#> 7 cli_vec_plain 28.9µs 30.7µs 31328. 848B 25.1
#> 8 fansi_vec_plain 36.4µs 38.4µs 25313. 4.59KB 20.3
#> 9 cli_txt_ansi 35.4µs 37.2µs 26068. 0B 20.9
#> 10 fansi_txt_ansi 44.5µs 46.7µs 20863. 5.12KB 16.9
#> 11 cli_txt_plain 26.9µs 28.7µs 33900. 0B 27.1
#> 12 fansi_txt_plain 28.6µs 30.3µs 32144. 688B 22.5
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 165.45µs 173.19µs 5601. 104.31KB 19.1
#> 2 fansi_ansi 128.18µs 135.43µs 7205. 106.35KB 19.3
#> 3 base_ansi 4.16µs 4.53µs 214797. 224B 21.5
#> 4 cli_plain 164.35µs 172µs 5659. 8.09KB 19.0
#> 5 fansi_plain 125.81µs 132.75µs 7238. 9.62KB 19.2
#> 6 base_plain 3.62µs 3.9µs 247575. 0B 0
#> 7 cli_vec_ansi 7.57ms 7.72ms 129. 823.77KB 28.9
#> 8 fansi_vec_ansi 1.08ms 1.12ms 859. 846.81KB 17.5
#> 9 base_vec_ansi 159.63µs 165.24µs 5929. 22.7KB 2.05
#> 10 cli_vec_plain 7.71ms 7.84ms 126. 823.77KB 25.8
#> 11 fansi_vec_plain 1.04ms 1.08ms 890. 845.98KB 17.7
#> 12 base_vec_plain 106.56µs 110.01µs 8916. 848B 4.07
#> 13 cli_txt_ansi 3.44ms 3.48ms 284. 63.6KB 0
#> 14 fansi_txt_ansi 1.55ms 1.57ms 632. 35.05KB 2.02
#> 15 base_txt_ansi 138.29µs 149.71µs 6547. 18.47KB 2.03
#> 16 cli_txt_plain 2.37ms 2.41ms 413. 63.6KB 0
#> 17 fansi_txt_plain 529.69µs 568.88µs 1736. 30.6KB 6.20
#> 18 base_txt_plain 87.53µs 90.81µs 10784. 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 151.05µs 159.8µs 6017. 33.81KB 23.8
#> 2 fansi_ansi 54.48µs 58.56µs 16299. 31.43KB 21.4
#> 3 base_ansi 1.05µs 1.09µs 867019. 4.2KB 0
#> 4 cli_plain 147.3µs 154.99µs 6219. 0B 22.3
#> 5 fansi_plain 53.63µs 56.52µs 17183. 872B 23.6
#> 6 base_plain 990.93ns 1.03µs 912273. 0B 0
#> 7 cli_vec_ansi 275.91µs 284.93µs 3455. 16.73KB 12.6
#> 8 fansi_vec_ansi 122.94µs 128.03µs 7564. 5.59KB 12.6
#> 9 base_vec_ansi 36.07µs 36.48µs 27095. 848B 0
#> 10 cli_vec_plain 228.43µs 238.72µs 4096. 16.73KB 14.8
#> 11 fansi_vec_plain 119.34µs 124.28µs 7856. 5.59KB 12.6
#> 12 base_vec_plain 30.18µs 30.87µs 31999. 848B 0
#> 13 cli_txt_ansi 158.15µs 165.35µs 5893. 0B 21.3
#> 14 fansi_txt_ansi 53.87µs 57.65µs 16854. 872B 21.3
#> 15 base_txt_ansi 1.09µs 1.14µs 828871. 0B 82.9
#> 16 cli_txt_plain 147.64µs 155.53µs 6273. 0B 21.3
#> 17 fansi_txt_plain 53.62µs 57.7µs 16404. 872B 23.8
#> 18 base_txt_plain 1.01µs 1.05µs 910095. 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 403.28µs 428.23µs 2296. 0B 21.5
#> 2 fansi_ansi 97.48µs 104.14µs 9290. 97.33KB 19.1
#> 3 base_ansi 38.6µs 41.04µs 23347. 0B 21.0
#> 4 cli_plain 278.49µs 292.56µs 3345. 0B 19.1
#> 5 fansi_plain 96.91µs 102.34µs 9488. 872B 22.6
#> 6 base_plain 31.69µs 33.45µs 28951. 0B 17.4
#> 7 cli_vec_ansi 42.83ms 42.83ms 23.3 2.48KB 257.
#> 8 fansi_vec_ansi 245.26µs 254.78µs 3858. 7.25KB 10.4
#> 9 base_vec_ansi 2.25ms 2.35ms 424. 48.18KB 24.9
#> 10 cli_vec_plain 29.16ms 29.27ms 34.1 2.48KB 38.3
#> 11 fansi_vec_plain 204.5µs 213.16µs 4585. 6.42KB 12.5
#> 12 base_vec_plain 1.63ms 1.7ms 583. 47.4KB 24.8
#> 13 cli_txt_ansi 24.22ms 24.4ms 40.9 507.59KB 10.2
#> 14 fansi_txt_ansi 233.4µs 242.68µs 4050. 6.77KB 10.4
#> 15 base_txt_ansi 1.24ms 1.29ms 761. 582.06KB 18.5
#> 16 cli_txt_plain 1.27ms 1.31ms 746. 369.84KB 18.2
#> 17 fansi_txt_plain 185.36µs 192.98µs 5032. 2.51KB 10.4
#> 18 base_txt_plain 845.45µs 881.31µs 1109. 367.31KB 20.7
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.96µs 7.76µs 123007. 24.81KB 24.6
#> 2 fansi_ansi 79.42µs 84.26µs 11421. 28.48KB 21.5
#> 3 base_ansi 1.01µs 1.06µs 863271. 0B 0
#> 4 cli_plain 6.71µs 7.45µs 128225. 0B 38.5
#> 5 fansi_plain 79.06µs 84.37µs 11416. 1.98KB 20.1
#> 6 base_plain 973.12ns 1.03µs 916158. 0B 0
#> 7 cli_vec_ansi 27.32µs 28.39µs 34575. 1.7KB 6.92
#> 8 fansi_vec_ansi 114.3µs 119.37µs 8166. 8.86KB 14.9
#> 9 base_vec_ansi 5.93µs 6.06µs 161606. 848B 0
#> 10 cli_vec_plain 23.07µs 24.2µs 40102. 1.7KB 12.0
#> 11 fansi_vec_plain 108.94µs 113.34µs 8602. 8.86KB 14.9
#> 12 base_vec_plain 5.75µs 5.87µs 166460. 848B 0
#> 13 cli_txt_ansi 6.79µs 7.42µs 129874. 0B 26.0
#> 14 fansi_txt_ansi 77.31µs 82.47µs 11800. 1.98KB 21.4
#> 15 base_txt_ansi 5.18µs 5.23µs 186185. 0B 0
#> 16 cli_txt_plain 7.58µs 8.22µs 117945. 0B 35.4
#> 17 fansi_txt_plain 78.34µs 82.92µs 11743. 1.98KB 19.2
#> 18 base_txt_plain 3.36µs 3.44µs 260241. 0B 26.0
ansi_tolower()
, ansi_toupper()
bench::mark(
cli_ansi = ansi_tolower(ansi),
base_ansi = tolower(ansi),
cli_plain = ansi_tolower(plain),
base_plain = tolower(plain),
cli_vec_ansi = ansi_tolower(vec_ansi),
base_vec_ansi = tolower(vec_ansi),
cli_vec_plain = ansi_tolower(vec_plain),
base_vec_plain = tolower(vec_plain),
cli_txt_ansi = ansi_tolower(txt_ansi),
base_txt_ansi = tolower(txt_ansi),
cli_txt_plain = ansi_tolower(txt_plain),
base_txt_plain = tolower(txt_plain),
check = FALSE
)
#> # A tibble: 12 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 cli_ansi 106.77µs 112.3µs 8650. 11.85KB 14.7
#> 2 base_ansi 1.3µs 1.34µs 705129. 0B 70.5
#> 3 cli_plain 85.86µs 89.91µs 10779. 8.73KB 14.6
#> 4 base_plain 973ns 1.04µs 931508. 0B 0
#> 5 cli_vec_ansi 4.16ms 4.28ms 233. 838.77KB 26.4
#> 6 base_vec_ansi 74.23µs 74.68µs 13206. 848B 0
#> 7 cli_vec_plain 2.32ms 2.4ms 416. 816.9KB 30.5
#> 8 base_vec_plain 43.69µs 44.07µs 22389. 848B 0
#> 9 cli_txt_ansi 13.64ms 13.74ms 72.6 114.42KB 6.60
#> 10 base_txt_ansi 74.8µs 76.11µs 13001. 0B 0
#> 11 cli_txt_plain 272.93µs 283.27µs 3461. 18.16KB 4.06
#> 12 base_txt_plain 41.3µs 43.24µs 22947. 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.7µs 116.6µs 8200. 0B 21.3
#> 2 base_ansi 16.6µs 17.9µs 53452. 0B 21.4
#> 3 cli_plain 110.1µs 116.1µs 8334. 0B 21.3
#> 4 base_plain 16.7µs 17.9µs 53928. 0B 21.6
#> 5 cli_vec_ansi 205.2µs 214.9µs 4549. 7.2KB 12.5
#> 6 base_vec_ansi 55.7µs 64.1µs 15350. 1.66KB 4.74
#> 7 cli_vec_plain 188.1µs 199.3µs 4921. 7.2KB 12.5
#> 8 base_vec_plain 49.7µs 57µs 17075. 1.66KB 6.11
#> 9 cli_txt_ansi 177.1µs 183.5µs 5320. 0B 14.6
#> 10 base_txt_ansi 38.1µs 39.4µs 24212. 0B 9.69
#> 11 cli_txt_plain 161.5µs 167.2µs 5827. 0B 14.6
#> 12 base_txt_plain 33.7µs 35.1µs 27811. 0B 11.1
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.07µs 8.72µs 111312. 0B 22.3
#> 2 base 881.03ns 922.13ns 986240. 0B 0
#> 3 cli_vec 23.19µs 23.96µs 40926. 448B 12.3
#> 4 base_vec 11.59µs 11.84µs 83280. 448B 0
#> 5 cli_txt 23.38µs 24.07µs 40768. 0B 8.16
#> 6 base_txt 12.39µs 12.46µs 78937. 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.8µs 110624. 0B 22.1
#> 2 base 1.26µs 1.35µs 700220. 0B 0
#> 3 cli_vec 28.74µs 29.63µs 33133. 448B 6.63
#> 4 base_vec 51.1µs 51.71µs 19124. 448B 2.01
#> 5 cli_txt 29.02µs 29.84µs 32792. 0B 6.56
#> 6 base_txt 87.46µs 87.97µs 11249. 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.54µs 9.19µs 105470. 0B 31.7
#> 2 base 842.03ns 912.11ns 1013847. 0B 0
#> 3 cli_vec 19.44µs 20.37µs 47317. 448B 14.2
#> 4 base_vec 11.58µs 11.82µs 83404. 448B 0
#> 5 cli_txt 20.08µs 20.9µs 46812. 0B 9.36
#> 6 base_txt 12.38µs 12.47µs 78762. 0B 7.88
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.44µs 7.03µs 137790. 22.1KB 27.6
#> 2 base 1.04µs 1.1µs 838137. 0B 83.8
#> 3 cli_vec 29.17µs 30.13µs 32639. 1.7KB 6.53
#> 4 base_vec 7.86µs 8.34µs 117987. 848B 0
#> 5 cli_txt 6.36µs 7.07µs 136877. 0B 41.1
#> 6 base_txt 5.47µs 5.53µs 176800. 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-24
#> 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 2025-04-24 [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.1 2024-09-17 [1] any (@2.1.1)
#> 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.
#>
#> ─────────────────────────────────────────────────────────────────────