diff options
Diffstat (limited to 'intl/l10n/rust/l10nregistry-rs/benches')
-rw-r--r-- | intl/l10n/rust/l10nregistry-rs/benches/localization.rs | 70 | ||||
-rw-r--r-- | intl/l10n/rust/l10nregistry-rs/benches/preferences.rs | 65 | ||||
-rw-r--r-- | intl/l10n/rust/l10nregistry-rs/benches/registry.rs | 133 | ||||
-rw-r--r-- | intl/l10n/rust/l10nregistry-rs/benches/solver.rs | 120 | ||||
-rw-r--r-- | intl/l10n/rust/l10nregistry-rs/benches/source.rs | 60 |
5 files changed, 448 insertions, 0 deletions
diff --git a/intl/l10n/rust/l10nregistry-rs/benches/localization.rs b/intl/l10n/rust/l10nregistry-rs/benches/localization.rs new file mode 100644 index 0000000000..696cc244ed --- /dev/null +++ b/intl/l10n/rust/l10nregistry-rs/benches/localization.rs @@ -0,0 +1,70 @@ +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use fluent_bundle::FluentArgs; +use fluent_fallback::{types::L10nKey, Localization}; +use fluent_testing::get_scenarios; +use l10nregistry::testing::TestFileFetcher; + +fn preferences_bench(c: &mut Criterion) { + let fetcher = TestFileFetcher::new(); + + let mut group = c.benchmark_group("localization/scenarios"); + + for scenario in get_scenarios() { + let res_ids = scenario.res_ids.clone(); + let l10n_keys: Vec<(String, Option<FluentArgs>)> = scenario + .queries + .iter() + .map(|q| { + ( + q.input.id.clone(), + q.input.args.as_ref().map(|args| { + let mut result = FluentArgs::new(); + for arg in args.as_slice() { + result.set(arg.id.clone(), arg.value.clone()); + } + result + }), + ) + }) + .collect(); + + group.bench_function(format!("{}/format_value_sync", scenario.name), |b| { + b.iter(|| { + let (env, reg) = fetcher.get_registry_and_environment(&scenario); + let mut errors = vec![]; + + let loc = Localization::with_env(res_ids.clone(), true, env.clone(), reg.clone()); + let bundles = loc.bundles(); + + for key in l10n_keys.iter() { + bundles.format_value_sync(&key.0, key.1.as_ref(), &mut errors); + } + }) + }); + + let keys: Vec<L10nKey> = l10n_keys + .into_iter() + .map(|key| L10nKey { + id: key.0.into(), + args: key.1, + }) + .collect(); + group.bench_function(format!("{}/format_messages_sync", scenario.name), |b| { + b.iter(|| { + let (env, reg) = fetcher.get_registry_and_environment(&scenario); + let mut errors = vec![]; + let loc = Localization::with_env(res_ids.clone(), true, env.clone(), reg.clone()); + let bundles = loc.bundles(); + bundles.format_messages_sync(&keys, &mut errors); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, preferences_bench); +criterion_main!(benches); diff --git a/intl/l10n/rust/l10nregistry-rs/benches/preferences.rs b/intl/l10n/rust/l10nregistry-rs/benches/preferences.rs new file mode 100644 index 0000000000..e4405c6537 --- /dev/null +++ b/intl/l10n/rust/l10nregistry-rs/benches/preferences.rs @@ -0,0 +1,65 @@ +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use fluent_testing::get_scenarios; +use l10nregistry::testing::TestFileFetcher; + +use unic_langid::LanguageIdentifier; + +fn preferences_bench(c: &mut Criterion) { + let fetcher = TestFileFetcher::new(); + + let mut group = c.benchmark_group("registry/scenarios"); + + for scenario in get_scenarios() { + let res_ids = scenario.res_ids.clone(); + + let locales: Vec<LanguageIdentifier> = scenario + .locales + .iter() + .map(|l| l.parse().unwrap()) + .collect(); + + group.bench_function(format!("{}/sync/first_bundle", scenario.name), |b| { + b.iter(|| { + let reg = fetcher.get_registry(&scenario); + let mut bundles = + reg.generate_bundles_sync(locales.clone().into_iter(), res_ids.clone()); + for _ in 0..locales.len() { + if bundles.next().is_some() { + break; + } + } + }) + }); + + #[cfg(feature = "tokio")] + { + use futures::stream::StreamExt; + + let rt = tokio::runtime::Runtime::new().unwrap(); + + group.bench_function(&format!("{}/async/first_bundle", scenario.name), |b| { + b.iter(|| { + rt.block_on(async { + let reg = fetcher.get_registry(&scenario); + + let mut bundles = + reg.generate_bundles(locales.clone().into_iter(), res_ids.clone()); + for _ in 0..locales.len() { + if bundles.next().await.is_some() { + break; + } + } + }); + }) + }); + } + } + + group.finish(); +} + +criterion_group!(benches, preferences_bench); +criterion_main!(benches); diff --git a/intl/l10n/rust/l10nregistry-rs/benches/registry.rs b/intl/l10n/rust/l10nregistry-rs/benches/registry.rs new file mode 100644 index 0000000000..959b510943 --- /dev/null +++ b/intl/l10n/rust/l10nregistry-rs/benches/registry.rs @@ -0,0 +1,133 @@ +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use futures::stream::StreamExt; +use l10nregistry::source::ResourceId; +use l10nregistry::testing::{FileSource, RegistrySetup, TestFileFetcher}; +use unic_langid::LanguageIdentifier; + +fn get_paths() -> Vec<ResourceId> { + let paths: Vec<&'static str> = vec![ + "branding/brand.ftl", + "browser/sanitize.ftl", + "browser/preferences/blocklists.ftl", + "browser/preferences/colors.ftl", + "browser/preferences/selectBookmark.ftl", + "browser/preferences/connection.ftl", + "browser/preferences/addEngine.ftl", + "browser/preferences/siteDataSettings.ftl", + "browser/preferences/fonts.ftl", + "browser/preferences/languages.ftl", + "browser/preferences/preferences.ftl", + "security/certificates/certManager.ftl", + "security/certificates/deviceManager.ftl", + "toolkit/global/textActions.ftl", + "toolkit/printing/printUI.ftl", + "toolkit/updates/history.ftl", + "toolkit/featuregates/features.ftl", + ]; + + paths.into_iter().map(ResourceId::from).collect() +} + +fn registry_bench(c: &mut Criterion) { + let en_us: LanguageIdentifier = "en-US".parse().unwrap(); + let mut group = c.benchmark_group("non-metasource"); + + let setup = RegistrySetup::new( + "test", + vec![ + FileSource::new("toolkit", None, vec![en_us.clone()], "toolkit/{locale}/"), + FileSource::new("browser", None, vec![en_us.clone()], "browser/{locale}/"), + FileSource::new("toolkit", None, vec![en_us.clone()], "toolkit/{locale}/"), + FileSource::new("browser", None, vec![en_us.clone()], "browser/{locale}/"), + ], + vec![en_us.clone()], + ); + let fetcher = TestFileFetcher::new(); + let (_, reg) = fetcher.get_registry_and_environment(setup); + + group.bench_function(&format!("serial",), |b| { + b.iter(|| { + let lang_ids = vec![en_us.clone()]; + let mut i = reg.generate_bundles_sync(lang_ids.into_iter(), get_paths()); + while let Some(_) = i.next() {} + }) + }); + + let rt = tokio::runtime::Runtime::new().unwrap(); + group.bench_function(&format!("parallel",), |b| { + b.iter(|| { + let lang_ids = vec![en_us.clone()]; + let mut i = reg.generate_bundles(lang_ids.into_iter(), get_paths()); + rt.block_on(async { while let Some(_) = i.next().await {} }); + }) + }); + + group.finish(); +} + +fn registry_metasource_bench(c: &mut Criterion) { + let en_us: LanguageIdentifier = "en-US".parse().unwrap(); + let mut group = c.benchmark_group("metasource"); + + let setup = RegistrySetup::new( + "test", + vec![ + FileSource::new( + "toolkit", + Some("app"), + vec![en_us.clone()], + "toolkit/{locale}/", + ), + FileSource::new( + "browser", + Some("app"), + vec![en_us.clone()], + "browser/{locale}/", + ), + FileSource::new( + "toolkit", + Some("langpack"), + vec![en_us.clone()], + "toolkit/{locale}/", + ), + FileSource::new( + "browser", + Some("langpack"), + vec![en_us.clone()], + "browser/{locale}/", + ), + ], + vec![en_us.clone()], + ); + let fetcher = TestFileFetcher::new(); + let (_, reg) = fetcher.get_registry_and_environment(setup); + + group.bench_function(&format!("serial",), |b| { + b.iter(|| { + let lang_ids = vec![en_us.clone()]; + let mut i = reg.generate_bundles_sync(lang_ids.into_iter(), get_paths()); + while let Some(_) = i.next() {} + }) + }); + + let rt = tokio::runtime::Runtime::new().unwrap(); + group.bench_function(&format!("parallel",), |b| { + b.iter(|| { + let lang_ids = vec![en_us.clone()]; + let mut i = reg.generate_bundles(lang_ids.into_iter(), get_paths()); + rt.block_on(async { while let Some(_) = i.next().await {} }); + }) + }); + + group.finish(); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(10); + targets = registry_bench, registry_metasource_bench +); +criterion_main!(benches); diff --git a/intl/l10n/rust/l10nregistry-rs/benches/solver.rs b/intl/l10n/rust/l10nregistry-rs/benches/solver.rs new file mode 100644 index 0000000000..25906fa7c0 --- /dev/null +++ b/intl/l10n/rust/l10nregistry-rs/benches/solver.rs @@ -0,0 +1,120 @@ +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use futures::stream::Collect; +use futures::stream::FuturesOrdered; +use futures::StreamExt; +use l10nregistry::solver::testing::get_scenarios; +use l10nregistry::solver::{AsyncTester, ParallelProblemSolver, SerialProblemSolver, SyncTester}; +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub struct MockTester { + values: Vec<Vec<bool>>, +} + +impl SyncTester for MockTester { + fn test_sync(&self, res_idx: usize, source_idx: usize) -> bool { + self.values[res_idx][source_idx] + } +} + +pub struct SingleTestResult(bool); + +impl Future for SingleTestResult { + type Output = bool; + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { + self.0.into() + } +} + +pub type ResourceSetStream = Collect<FuturesOrdered<SingleTestResult>, Vec<bool>>; +pub struct TestResult(ResourceSetStream); + +impl std::marker::Unpin for TestResult {} + +impl Future for TestResult { + type Output = Vec<bool>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + let pinned = Pin::new(&mut self.0); + pinned.poll(cx) + } +} + +impl AsyncTester for MockTester { + type Result = TestResult; + + fn test_async(&self, query: Vec<(usize, usize)>) -> Self::Result { + let futures = query + .into_iter() + .map(|(res_idx, source_idx)| SingleTestResult(self.test_sync(res_idx, source_idx))) + .collect::<Vec<_>>(); + TestResult(futures.into_iter().collect::<FuturesOrdered<_>>().collect()) + } +} + +struct TestStream<'t> { + solver: ParallelProblemSolver<MockTester>, + tester: &'t MockTester, +} + +impl<'t> TestStream<'t> { + pub fn new(solver: ParallelProblemSolver<MockTester>, tester: &'t MockTester) -> Self { + Self { solver, tester } + } +} + +impl<'t> futures::stream::Stream for TestStream<'t> { + type Item = Vec<usize>; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll<Option<Self::Item>> { + let tester = self.tester; + let solver = &mut self.solver; + let pinned = std::pin::Pin::new(solver); + pinned + .try_poll_next(cx, tester, false) + .map(|v| v.ok().flatten()) + } +} + +fn solver_bench(c: &mut Criterion) { + let scenarios = get_scenarios(); + + let mut group = c.benchmark_group("solver"); + + for scenario in scenarios { + let tester = MockTester { + values: scenario.values.clone(), + }; + + group.bench_function(&format!("serial/{}", &scenario.name), |b| { + b.iter(|| { + let mut gen = SerialProblemSolver::new(scenario.width, scenario.depth); + while let Ok(Some(_)) = gen.try_next(&tester, false) {} + }) + }); + + { + let rt = tokio::runtime::Runtime::new().unwrap(); + + group.bench_function(&format!("parallel/{}", &scenario.name), |b| { + b.iter(|| { + let gen = ParallelProblemSolver::new(scenario.width, scenario.depth); + let mut t = TestStream::new(gen, &tester); + rt.block_on(async { while let Some(_) = t.next().await {} }); + }) + }); + } + } + group.finish(); +} + +criterion_group!(benches, solver_bench); +criterion_main!(benches); diff --git a/intl/l10n/rust/l10nregistry-rs/benches/source.rs b/intl/l10n/rust/l10nregistry-rs/benches/source.rs new file mode 100644 index 0000000000..35668781da --- /dev/null +++ b/intl/l10n/rust/l10nregistry-rs/benches/source.rs @@ -0,0 +1,60 @@ +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use fluent_testing::get_scenarios; +use l10nregistry::testing::TestFileFetcher; + +use unic_langid::LanguageIdentifier; + +fn get_locales<S>(input: &[S]) -> Vec<LanguageIdentifier> +where + S: AsRef<str>, +{ + input.iter().map(|s| s.as_ref().parse().unwrap()).collect() +} + +fn source_bench(c: &mut Criterion) { + let fetcher = TestFileFetcher::new(); + + let mut group = c.benchmark_group("source/scenarios"); + + for scenario in get_scenarios() { + let res_ids = scenario.res_ids.clone(); + + let locales: Vec<LanguageIdentifier> = get_locales(&scenario.locales); + + let sources: Vec<_> = scenario + .file_sources + .iter() + .map(|s| { + fetcher.get_test_file_source(&s.name, None, get_locales(&s.locales), &s.path_scheme) + }) + .collect(); + + group.bench_function(format!("{}/has_file", scenario.name), |b| { + b.iter(|| { + for source in &sources { + for res_id in &res_ids { + source.has_file(&locales[0], &res_id); + } + } + }) + }); + + group.bench_function(format!("{}/sync/fetch_file_sync", scenario.name), |b| { + b.iter(|| { + for source in &sources { + for res_id in &res_ids { + source.fetch_file_sync(&locales[0], &res_id, false); + } + } + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, source_bench); +criterion_main!(benches); |