@@ -3,138 +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
27
+ trait Testable {
28
+ type Input ;
17
29
18
- impl Memoizable for TF {
19
- type Args = ( Time , ) ;
30
+ fn execute ( & self , input : Self :: Input ) ;
31
+ }
20
32
21
- type Provider = icu_provider_blob:: BlobDataProvider ;
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
+ }
22
78
23
- /// If the construtor is fallible, than errors can be described here.
24
- type Error = ( ) ;
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
+ ) ;
25
115
26
- /// This function wires together the `Args` and `Error` type to construct
27
- /// the intl API. In our example, there is
28
- fn construct (
29
- lang : LanguageIdentifier ,
30
- args : Self :: Args ,
31
- provider : Option < & Self :: Provider > ,
32
- ) -> Result < Self , Self :: Error > {
33
- Ok ( Self (
34
- TimeFormatter :: try_new_with_length_with_buffer_provider (
35
- provider. unwrap ( ) , & lang. into ( ) , args. 0 ) . unwrap ( ) ,
36
- ) )
37
- }
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
+ } ;
38
125
}
39
126
40
- const SETS : usize = 10 ;
41
- const REPS : usize = 10 ;
42
-
43
- fn construct_lang_bench ( c : & mut Criterion ) {
44
- let lang: LanguageIdentifier = "en-US" . parse ( ) . unwrap ( ) ;
45
- let provider = BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
46
-
47
- c. bench_with_input (
48
- BenchmarkId :: new ( "construct_lang" , & lang) ,
49
- & ( lang, provider) ,
50
- |b, ( lang, provider) | {
51
- b. iter ( || {
52
- let _ = IntlLangMemoizer :: new ( lang. clone ( ) , Some ( provider) ) ;
53
- } ) ;
54
- } ,
55
- ) ;
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
+ } ;
56
137
}
57
138
58
- fn populate_lang ( c : & mut Criterion ) {
59
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
60
-
61
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
62
- let provider = BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
63
- let construct_args = ( Time :: Short , ) ;
64
-
65
- c. bench_with_input (
66
- BenchmarkId :: new ( "populate_lang" , & lang) ,
67
- & ( construct_args, provider) ,
68
- |b : & mut Bencher , ( construct_args, provider) | {
69
- b. iter ( || {
70
- let memoizer = IntlLangMemoizer :: new ( lang. clone ( ) , Some ( provider) ) ;
71
- for _ in 0 ..SETS {
72
- for _ in 0 ..REPS {
73
- let _ = memoizer. with_try_get :: < TF , _ , _ > ( construct_args, |intl_example| {
74
- intl_example. 0 . format_to_string ( & input)
75
- } ) ;
76
- }
77
- }
78
- } ) ;
79
- } ,
80
- ) ;
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
+ } ;
81
150
}
82
151
83
- fn without_memoizer ( c : & mut Criterion ) {
84
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
85
- let provider = BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
86
- let construct_args = ( Time :: Short , ) ;
87
-
88
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
89
-
90
- c. bench_with_input (
91
- BenchmarkId :: new ( "without_memoizer" , & lang) ,
92
- & ( construct_args, provider) ,
93
- |b : & mut Bencher , ( construct_args, provider) | {
94
- b. iter ( || {
95
- for _ in 0 ..SETS {
96
- for _ in 0 ..REPS {
97
- let formatter =
98
- TimeFormatter :: try_new_with_length_with_buffer_provider ( provider, & lang. clone ( ) . into ( ) , construct_args. 0 )
99
- . unwrap ( ) ;
100
- let _ = formatter. format ( & input) ;
101
- }
102
- }
103
- } ) ;
104
- } ,
105
- ) ;
106
- }
152
+ fn bench_variants ( c : & mut Criterion ) {
153
+ let lang: LanguageIdentifier = "und" . parse ( ) . unwrap ( ) ;
107
154
108
- fn without_memoizer_hoisted ( c : & mut Criterion ) {
109
- let lang: LanguageIdentifier = "en" . parse ( ) . unwrap ( ) ;
110
- let provider = BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
111
- let construct_args = ( Time :: Short , ) ;
112
-
113
- let input = DateTime :: try_new_gregorian_datetime ( 2020 , 9 , 1 , 12 , 34 , 28 ) . unwrap ( ) ;
114
-
115
- c. bench_with_input (
116
- BenchmarkId :: new ( "without_memoizer_hoisted" , & lang) ,
117
- & ( construct_args, provider) ,
118
- |b : & mut Bencher , ( construct_args, provider) | {
119
- b. iter ( || {
120
- for _ in 0 ..SETS {
121
- let formatter =
122
- TimeFormatter :: try_new_with_length_with_buffer_provider ( provider, & lang. clone ( ) . into ( ) , construct_args. 0 )
123
- . unwrap ( ) ;
124
- for _ in 0 ..REPS {
125
- let _ = formatter. format ( & input) ;
155
+ let provider =
156
+ BlobDataProvider :: try_new_from_static_blob ( ICU4X_DATA ) . expect ( "Failed to load data" ) ;
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)
126
175
}
127
- }
128
- } ) ;
129
- } ,
130
- ) ;
176
+ "plurals" => {
177
+ without_memoizer_hoisted ! ( PR , b, lang, provider, pr_args, * count, pr_input)
178
+ }
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
+ }
131
205
}
132
206
133
- criterion_group ! (
134
- benches,
135
- construct_lang_bench,
136
- populate_lang,
137
- without_memoizer,
138
- without_memoizer_hoisted
139
- ) ;
207
+ criterion_group ! ( benches, bench_variants, ) ;
140
208
criterion_main ! ( benches) ;
0 commit comments