@@ -3,151 +3,206 @@ use criterion::criterion_main;
3
3
use criterion:: Criterion ;
4
4
use criterion:: { Bencher , BenchmarkId } ;
5
5
use icu_calendar:: DateTime ;
6
- use icu_datetime:: { options:: length:: Time , TimeFormatter } ;
6
+ use icu_datetime:: {
7
+ options:: length:: { Date , Time } ,
8
+ // DateTimeFormatterOptions,
9
+ DateFormatter ,
10
+ // DateTimeFormatter,
11
+ TimeFormatter ,
12
+ } ;
13
+ // use icu_collator::{Collator, CollatorOptions};
14
+ // use icu_decimal::{FixedDecimalFormatter, options::FixedDecimalFormatterOptions};
15
+ // use fixed_decimal::FixedDecimal;
16
+ use icu_list:: { ListFormatter , ListLength } ;
7
17
use icu_locid:: LanguageIdentifier ;
18
+ use icu_plurals:: { PluralRuleType , PluralRules } ;
8
19
use intl_memoizer:: { IntlLangMemoizer , Memoizable } ;
9
-
10
- struct TF ( pub TimeFormatter ) ;
20
+ use std:: hint:: black_box;
11
21
12
22
use icu_provider_blob:: BlobDataProvider ;
13
23
const ICU4X_DATA : & [ u8 ] = include_bytes ! ( concat!(
14
- "/Users/zibi/projects/icu-perf/data/icu4x-1.4-datetime .postcard"
24
+ "/Users/zibi/projects/icu-perf/data/icu4x-1.4.postcard"
15
25
) ) ;
16
26
17
- impl Memoizable for TF {
18
- type Args = ( Time , ) ;
19
-
20
- type Provider = icu_provider_blob:: BlobDataProvider ;
21
-
22
- /// If the construtor is fallible, than errors can be described here.
23
- type Error = ( ) ;
24
-
25
- /// This function wires together the `Args` and `Error` type to construct
26
- /// the intl API. In our example, there is
27
- fn construct (
28
- lang : LanguageIdentifier ,
29
- args : Self :: Args ,
30
- provider : Option < & Self :: Provider > ,
31
- ) -> Result < Self , Self :: Error > {
32
- Ok ( Self (
33
- TimeFormatter :: try_new_with_length_with_buffer_provider (
34
- provider. unwrap ( ) ,
35
- & lang. into ( ) ,
36
- args. 0 ,
37
- )
38
- . unwrap ( ) ,
39
- ) )
40
- }
27
+ trait Testable {
28
+ type Input ;
29
+
30
+ fn execute ( & self , input : Self :: Input ) ;
41
31
}
42
32
43
- const SETS : usize = 10 ;
44
- const REPS : usize = 10 ;
33
+ macro_rules! define_testable_type {
34
+ ( $name: ident, $type: ident, $args: tt, $constructor: ident, $method: ident, $input: ty) => {
35
+ define_testable_type!( $name, $type, $args, $constructor) ;
36
+
37
+ impl Testable for $name {
38
+ type Input = $input;
39
+
40
+ fn execute( & self , input: Self :: Input ) {
41
+ let _ = self . 0. $method( input) ;
42
+ }
43
+ }
44
+ } ;
45
+
46
+ ( $name: ident, $type: ident, $args: tt, $constructor: ident, $method: ident, ref $input: ty) => {
47
+ define_testable_type!( $name, $type, $args, $constructor) ;
48
+
49
+ impl Testable for $name {
50
+ type Input = $input;
51
+
52
+ fn execute( & self , input: Self :: Input ) {
53
+ let _ = self . 0. $method( & input) ;
54
+ }
55
+ }
56
+ } ;
57
+
58
+ ( $name: ident, $type: ident, $args: tt, $constructor: ident) => {
59
+ struct $name( $type) ;
60
+
61
+ impl Memoizable for $name {
62
+ type Args = $args;
63
+ type Provider = icu_provider_blob:: BlobDataProvider ;
64
+ type Error = ( ) ;
65
+
66
+ fn construct(
67
+ lang: LanguageIdentifier ,
68
+ args: Self :: Args ,
69
+ provider: Option <& Self :: Provider >,
70
+ ) -> Result <Self , Self :: Error > {
71
+ Ok ( Self (
72
+ $type:: $constructor( provider. unwrap( ) , & lang. into( ) , args. 0 ) . unwrap( ) ,
73
+ ) )
74
+ }
75
+ }
76
+ } ;
77
+ }
45
78
46
- fn construct_lang_bench ( c : & mut Criterion ) {
47
- let lang: LanguageIdentifier = "en-US" . parse ( ) . unwrap ( ) ;
48
- let provider =
49
- BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
79
+ define_testable_type ! ( TF , TimeFormatter , ( Time , ) , try_new_with_length_with_buffer_provider, format_to_string, ref DateTime <icu_calendar:: Gregorian >) ;
80
+ define_testable_type ! ( DF , DateFormatter , ( Date , ) , try_new_with_length_with_buffer_provider, format_to_string, ref DateTime <icu_calendar:: AnyCalendar >) ;
81
+ // define_testable_type!(DTF, DateTimeFormatter, (DateTimeFormatterOptions, ), try_new_with_length_with_buffer_provider, format_to_string, ref DateTime<icu_calendar::AnyCalendar>);
82
+ define_testable_type ! (
83
+ PR ,
84
+ PluralRules ,
85
+ ( PluralRuleType , ) ,
86
+ try_new_with_buffer_provider,
87
+ category_for,
88
+ usize
89
+ ) ;
90
+ // define_testable_type!(
91
+ // C,
92
+ // Collator,
93
+ // (CollatorOptions,),
94
+ // try_new_with_buffer_provider,
95
+ // compare,
96
+ // &str,
97
+ // &str,
98
+ // );
99
+ // define_testable_type!(
100
+ // D,
101
+ // FixedDecimalFormatter,
102
+ // (FixedDecimalFormatterOptions,),
103
+ // try_new_with_buffer_provider,
104
+ // format_to_string,
105
+ // ref FixedDecimal
106
+ // );
107
+ define_testable_type ! (
108
+ LF ,
109
+ ListFormatter ,
110
+ ( ListLength , ) ,
111
+ try_new_and_with_length_with_buffer_provider,
112
+ format_to_string,
113
+ std:: vec:: IntoIter <String >
114
+ ) ;
50
115
51
- c . bench_with_input (
52
- BenchmarkId :: new ( "construct_lang" , & lang ) ,
53
- & ( lang , provider ) ,
54
- |b , ( lang, provider ) | {
55
- b . iter ( || {
56
- let _ = IntlLangMemoizer :: new ( lang . clone ( ) , Some ( provider ) ) ;
57
- } ) ;
58
- } ,
59
- ) ;
116
+ macro_rules! without_memoizer_hoisted {
117
+ ( $type : ident , $b : ident , $lang : ident , $provider : ident , $args : expr , $count : expr , $input : expr ) => {
118
+ $b . iter ( || {
119
+ let intl = $type :: construct ( $ lang. clone ( ) , black_box ( $args ) , Some ( $provider ) ) . unwrap ( ) ;
120
+ for _ in 0 ..$count {
121
+ let _ = intl . execute ( $input ) ;
122
+ }
123
+ } )
124
+ } ;
60
125
}
61
126
62
- fn populate_lang ( c : & mut Criterion ) {
63
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
64
-
65
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
66
- let provider =
67
- BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
68
- let construct_args = ( Time :: Short , ) ;
69
-
70
- c. bench_with_input (
71
- BenchmarkId :: new ( "populate_lang" , & lang) ,
72
- & ( construct_args, provider) ,
73
- |b : & mut Bencher , ( construct_args, provider) | {
74
- b. iter ( || {
75
- let memoizer = IntlLangMemoizer :: new ( lang. clone ( ) , Some ( provider) ) ;
76
- for _ in 0 ..SETS {
77
- for _ in 0 ..REPS {
78
- let _ = memoizer. with_try_get :: < TF , _ , _ > ( construct_args, |intl_example| {
79
- intl_example. 0 . format_to_string ( & input)
80
- } ) ;
81
- }
82
- }
83
- } ) ;
84
- } ,
85
- ) ;
127
+ macro_rules! without_memoizer {
128
+ ( $type: ident, $b: ident, $lang: ident, $provider: ident, $args: expr, $count: expr, $input: expr ) => {
129
+ $b. iter( || {
130
+ for _ in 0 ..$count {
131
+ let intl =
132
+ $type:: construct( $lang. clone( ) , black_box( $args) , Some ( $provider) ) . unwrap( ) ;
133
+ let _ = intl. execute( $input) ;
134
+ }
135
+ } )
136
+ } ;
86
137
}
87
138
88
- fn without_memoizer ( c : & mut Criterion ) {
89
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
90
- let provider =
91
- BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
92
- let construct_args = ( Time :: Short , ) ;
93
-
94
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
95
-
96
- c. bench_with_input (
97
- BenchmarkId :: new ( "without_memoizer" , & lang) ,
98
- & ( construct_args, provider) ,
99
- |b : & mut Bencher , ( construct_args, provider) | {
100
- b. iter ( || {
101
- for _ in 0 ..SETS {
102
- for _ in 0 ..REPS {
103
- let formatter = TimeFormatter :: try_new_with_length_with_buffer_provider (
104
- provider,
105
- & lang. clone ( ) . into ( ) ,
106
- construct_args. 0 ,
107
- )
108
- . unwrap ( ) ;
109
- let _ = formatter. format ( & input) ;
110
- }
111
- }
112
- } ) ;
113
- } ,
114
- ) ;
139
+ macro_rules! with_memoizer {
140
+ ( $type: ident, $b: ident, $lang: ident, $provider: ident, $args: expr, $count: expr, $input: expr ) => {
141
+ $b. iter( || {
142
+ let memoizer =
143
+ IntlLangMemoizer :: new( black_box( $lang. clone( ) ) , Some ( black_box( $provider) ) ) ;
144
+ for _ in 0 ..$count {
145
+ let _ =
146
+ memoizer. with_try_get( black_box( & $args) , |intl: & $type| intl. execute( $input) ) ;
147
+ }
148
+ } )
149
+ } ;
115
150
}
116
151
117
- fn without_memoizer_hoisted ( c : & mut Criterion ) {
118
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
152
+ fn bench_variants ( c : & mut Criterion ) {
153
+ let lang: LanguageIdentifier = "und" . parse ( ) . unwrap ( ) ;
154
+
119
155
let provider =
120
156
BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
121
- let construct_args = ( Time :: Short , ) ;
122
-
123
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
124
-
125
- c. bench_with_input (
126
- BenchmarkId :: new ( "without_memoizer_hoisted" , & lang) ,
127
- & ( construct_args, provider) ,
128
- |b : & mut Bencher , ( construct_args, provider) | {
129
- b. iter ( || {
130
- for _ in 0 ..SETS {
131
- let formatter = TimeFormatter :: try_new_with_length_with_buffer_provider (
132
- provider,
133
- & lang. clone ( ) . into ( ) ,
134
- construct_args. 0 ,
135
- )
136
- . unwrap ( ) ;
137
- for _ in 0 ..REPS {
138
- let _ = formatter. format ( & input) ;
157
+
158
+ let tf_input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
159
+ let tf_args = ( Time :: Short , ) ;
160
+
161
+ let pr_input = 5 ;
162
+ let pr_args = ( PluralRuleType :: Cardinal , ) ;
163
+
164
+ for component in [ "time" , "plurals" ] {
165
+ let mut group = c. benchmark_group ( component) ;
166
+ let counts: & [ usize ] = & [ 0 , 1 , 10 , 100 , 1000 , 10000 ] ;
167
+
168
+ for count in counts {
169
+ group. bench_with_input (
170
+ BenchmarkId :: new ( "without_memoizer_hoisted" , count) ,
171
+ & ( count, & provider) ,
172
+ |b : & mut Bencher , & ( count, provider) | match component {
173
+ "time" => {
174
+ without_memoizer_hoisted ! ( TF , b, lang, provider, tf_args, * count, tf_input)
175
+ }
176
+ "plurals" => {
177
+ without_memoizer_hoisted ! ( PR , b, lang, provider, pr_args, * count, pr_input)
139
178
}
140
- }
141
- } ) ;
142
- } ,
143
- ) ;
179
+ _ => unreachable ! ( ) ,
180
+ } ,
181
+ ) ;
182
+ group. bench_with_input (
183
+ BenchmarkId :: new ( "without_memoizer" , count) ,
184
+ & ( count, & provider) ,
185
+ |b : & mut Bencher , & ( count, provider) | match component {
186
+ "time" => without_memoizer ! ( TF , b, lang, provider, tf_args, * count, tf_input) ,
187
+ "plurals" => {
188
+ without_memoizer ! ( PR , b, lang, provider, pr_args, * count, pr_input)
189
+ }
190
+ _ => unreachable ! ( ) ,
191
+ } ,
192
+ ) ;
193
+ group. bench_with_input (
194
+ BenchmarkId :: new ( "with_memoizer" , count) ,
195
+ & ( count, & provider) ,
196
+ |b : & mut Bencher , & ( count, provider) | match component {
197
+ "time" => with_memoizer ! ( TF , b, lang, provider, tf_args, * count, tf_input) ,
198
+ "plurals" => with_memoizer ! ( PR , b, lang, provider, pr_args, * count, pr_input) ,
199
+ _ => unreachable ! ( ) ,
200
+ } ,
201
+ ) ;
202
+ }
203
+ group. finish ( ) ;
204
+ }
144
205
}
145
206
146
- criterion_group ! (
147
- benches,
148
- construct_lang_bench,
149
- populate_lang,
150
- without_memoizer,
151
- without_memoizer_hoisted
152
- ) ;
207
+ criterion_group ! ( benches, bench_variants, ) ;
153
208
criterion_main ! ( benches) ;
0 commit comments