Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! SmolStr vs String benchmarks.
use criterion::{criterion_group, criterion_main, Criterion};
use rand::distr::{Alphanumeric, SampleString};
use smol_str::{format_smolstr, SmolStr, StrExt, ToSmolStr};
use std::hint::black_box;

/// 12: small (inline)
/// 50: medium (heap)
/// 1000: large (heap)
const TEST_LENS: [usize; 3] = [12, 50, 1000];

fn format_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let n = rand::random_range(10000..99999);
        let str_len = len.checked_sub(n.to_smolstr().len()).unwrap();
        let str = Alphanumeric.sample_string(&mut rand::rng(), str_len);

        c.bench_function(&format!("SmolStr format_smolstr! len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = format_smolstr!("{str}-{n}"));
            assert_eq!(v, format!("{str}-{n}"));
        });
        c.bench_function(&format!("std format! len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = format!("{str}-{n}"));
            assert_eq!(v, format!("{str}-{n}"));
        });
    }
}

fn from_str_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let str = Alphanumeric.sample_string(&mut rand::rng(), len);

        c.bench_function(&format!("SmolStr::from len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = SmolStr::from(black_box(&str)));
            assert_eq!(v, str);
        });
        c.bench_function(&format!("std String::from len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = String::from(black_box(&str)));
            assert_eq!(v, str);
        });
    }
}

fn clone_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let str = Alphanumeric.sample_string(&mut rand::rng(), len);
        let smolstr = SmolStr::new(&str);

        c.bench_function(&format!("SmolStr::clone len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = smolstr.clone());
            assert_eq!(v, str);
        });
        c.bench_function(&format!("std String::clone len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.clone());
            assert_eq!(v, str);
        });
    }
}

fn eq_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let str = Alphanumeric.sample_string(&mut rand::rng(), len);
        let smolstr = SmolStr::new(&str);

        c.bench_function(&format!("SmolStr::eq len={len}"), |b| {
            let mut v = false;
            b.iter(|| v = smolstr == black_box(&str));
            assert!(v);
        });
        c.bench_function(&format!("std String::eq len={len}"), |b| {
            let mut v = false;
            b.iter(|| v = &str == black_box(&str));
            assert!(v);
        });
    }
}

fn to_lowercase_bench(c: &mut Criterion) {
    const END_CHAR: char = 'İ';

    for len in TEST_LENS {
        // mostly ascii seq with some non-ascii at the end
        let mut str = Alphanumeric.sample_string(&mut rand::rng(), len - END_CHAR.len_utf8());
        str.push(END_CHAR);
        let str = str.as_str();

        c.bench_function(&format!("SmolStr to_lowercase_smolstr len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.to_lowercase_smolstr());
            assert_eq!(v, str.to_lowercase());
        });
        c.bench_function(&format!("std to_lowercase len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.to_lowercase());
            assert_eq!(v, str.to_lowercase());
        });
    }
}

fn to_ascii_lowercase_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let str = Alphanumeric.sample_string(&mut rand::rng(), len);
        let str = str.as_str();

        c.bench_function(
            &format!("SmolStr to_ascii_lowercase_smolstr len={len}"),
            |b| {
                let mut v = <_>::default();
                b.iter(|| v = str.to_ascii_lowercase_smolstr());
                assert_eq!(v, str.to_ascii_lowercase());
            },
        );
        c.bench_function(&format!("std to_ascii_lowercase len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.to_ascii_lowercase());
            assert_eq!(v, str.to_ascii_lowercase());
        });
    }
}

fn replace_bench(c: &mut Criterion) {
    for len in TEST_LENS {
        let s_dash_s = Alphanumeric.sample_string(&mut rand::rng(), len / 2)
            + "-"
            + &Alphanumeric.sample_string(&mut rand::rng(), len - 1 - len / 2);
        let str = s_dash_s.as_str();

        c.bench_function(&format!("SmolStr replace_smolstr len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.replace_smolstr("-", "_"));
            assert_eq!(v, str.replace("-", "_"));
        });
        c.bench_function(&format!("std replace len={len}"), |b| {
            let mut v = <_>::default();
            b.iter(|| v = str.replace("-", "_"));
            assert_eq!(v, str.replace("-", "_"));
        });
    }
}

criterion_group!(
    benches,
    format_bench,
    from_str_bench,
    clone_bench,
    eq_bench,
    to_lowercase_bench,
    to_ascii_lowercase_bench,
    replace_bench,
);
criterion_main!(benches);