From eba3abb128276f8362d07a83c123ef2e46417814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 19 Jan 2024 17:35:17 +0100 Subject: [PATCH] Use `triomphe::Arc` to mitigate performance losses This change replaces `std::sync::Arc` with `triomphe::Arc`. The latter has no weak references, and is a lot faster because of that. --- README.md | 2 +- crates/support/Cargo.toml | 1 + crates/support/src/atomic_str.rs | 45 ++++++++++---------------------- src/lib.rs | 9 ++++--- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 0d74307..b8517bb 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ You can use `rust_i18n::set_locale` to set the global locale at runtime, so that rust_i18n::set_locale("zh-CN"); let locale = rust_i18n::locale(); -assert_eq!(*locale, "zh-CN"); +assert_eq!(&*locale, "zh-CN"); ``` ### Extend Backend diff --git a/crates/support/Cargo.toml b/crates/support/Cargo.toml index b064ad6..8cb7c1b 100644 --- a/crates/support/Cargo.toml +++ b/crates/support/Cargo.toml @@ -19,3 +19,4 @@ toml = "0.7.4" normpath = "1.1.1" lazy_static = "1" regex = "1" +triomphe = { version = "0.1.11", features = ["arc-swap"] } diff --git a/crates/support/src/atomic_str.rs b/crates/support/src/atomic_str.rs index 6e9e3bd..0dd0249 100644 --- a/crates/support/src/atomic_str.rs +++ b/crates/support/src/atomic_str.rs @@ -1,43 +1,35 @@ use std::fmt; -use std::sync::Arc; +use std::ops::Deref; -use arc_swap::{ArcSwap, Guard}; +use arc_swap::{ArcSwapAny, Guard}; +use triomphe::Arc; /// A thread-safe atomically reference-counting string. -pub struct AtomicStr(ArcSwap); +pub struct AtomicStr(ArcSwapAny>); /// A thread-safe view the string that was stored when `AtomicStr::as_str()` was called. struct GuardedStr(Guard>); -impl AsRef for GuardedStr { - fn as_ref(&self) -> &str { - self.0.as_str() - } -} +impl Deref for GuardedStr { + type Target = str; -impl fmt::Display for GuardedStr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.0.as_ref()) + fn deref(&self) -> &Self::Target { + self.0.as_str() } } impl AtomicStr { /// Create a new `AtomicStr` with the given value. - pub fn new(value: impl Into) -> Self { + pub fn new(value: &str) -> Self { let arced = Arc::new(value.into()); - Self(ArcSwap::new(arced)) + Self(ArcSwapAny::new(arced)) } /// Get the string slice. - pub fn as_str(&self) -> impl AsRef + fmt::Display { + pub fn as_str(&self) -> impl Deref { GuardedStr(self.0.load()) } - /// Get the cloned inner `Arc`. - pub fn clone_string(&self) -> Arc { - Guard::into_inner(self.0.load()) - } - /// Replaces the value at self with src. pub fn replace(&self, src: impl Into) { let arced = Arc::new(src.into()); @@ -45,23 +37,14 @@ impl AtomicStr { } } -impl From for AtomicStr -where - T: Into, -{ - fn from(value: T) -> Self { +impl From<&str> for AtomicStr { + fn from(value: &str) -> Self { Self::new(value) } } -impl From<&AtomicStr> for Arc { - fn from(value: &AtomicStr) -> Self { - value.clone_string() - } -} - impl fmt::Display for AtomicStr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.as_str()) + f.write_str(&self.as_str()) } } diff --git a/src/lib.rs b/src/lib.rs index 707b324..7bf5f2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ #![doc = include_str!("../README.md")] +use std::ops::Deref; + use once_cell::sync::Lazy; -use std::sync::Arc; #[doc(hidden)] pub use once_cell; @@ -16,8 +17,8 @@ pub fn set_locale(locale: &str) { } /// Get current locale -pub fn locale() -> Arc { - CURRENT_LOCALE.clone_string() +pub fn locale() -> impl Deref { + CURRENT_LOCALE.as_str() } /// Replace patterns and return a new string. @@ -110,7 +111,7 @@ pub fn replace_patterns(input: &str, patterns: &[&str], values: &[String]) -> St macro_rules! t { // t!("foo") ($key:expr) => { - crate::_rust_i18n_translate(rust_i18n::locale().as_str(), $key) + crate::_rust_i18n_translate(&rust_i18n::locale(), $key) }; // t!("foo", locale = "en")