@@ -3,138 +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
27+ trait Testable {
28+ type Input ;
1729
18- impl Memoizable for TF {
19- type Args = ( Time , ) ;
30+ fn execute ( & self , input : Self :: Input ) ;
31+ }
2032
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+ }
2278
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+ ) ;
25115
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+ } ;
38125}
39126
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+ } ;
56137}
57138
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+ } ;
81150}
82151
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 ( ) ;
107154
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)
126175 }
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+ }
131205}
132206
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, ) ;
140208criterion_main ! ( benches) ;
0 commit comments