@@ -3,151 +3,206 @@ use criterion::criterion_main;
33use criterion:: Criterion ;
44use criterion:: { Bencher , BenchmarkId } ;
55use 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 } ;
717use icu_locid:: LanguageIdentifier ;
18+ use icu_plurals:: { PluralRuleType , PluralRules } ;
819use intl_memoizer:: { IntlLangMemoizer , Memoizable } ;
9-
10- struct TF ( pub TimeFormatter ) ;
20+ use std:: hint:: black_box;
1121
1222use icu_provider_blob:: BlobDataProvider ;
1323const 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"
1525) ) ;
1626
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 ) ;
4131}
4232
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+ }
4578
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+ ) ;
50115
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+ } ;
60125}
61126
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+ } ;
86137}
87138
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+ } ;
115150}
116151
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+
119155 let provider =
120156 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)
139178 }
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+ }
144205}
145206
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, ) ;
153208criterion_main ! ( benches) ;
0 commit comments