Skip to content

Commit

Permalink
perf!: reduce cloning, add inline attribute (#78)
Browse files Browse the repository at this point in the history
* Refactor `Fraction` methods to reduce cloning

Revise the `Fraction` and `CurrencyAmount` methods to reduce unnecessary cloning and improve performance. Add trait constraints and modify functions to work with references, enhancing code efficiency and maintainability.

* Refactor to reduce unnecessary cloning

Updated methods to return references instead of owned values and removed redundant clone operations. This should reduce unnecessary heap allocations and improve performance by minimizing malloc overhead.

* Add inline attributes to improve function call performance

Annotated various functions and methods with #[inline] to suggest the compiler perform inline expansion, potentially enhancing performance for frequently called operations. This change spans across multiple modules, including token, weth9, base_currency, currency_amount, percent, fraction, price, compute_price_impact, and ether.
  • Loading branch information
shuhuiluo authored Sep 3, 2024
1 parent bcd486f commit 15f1d3d
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "uniswap-sdk-core"
version = "1.1.0"
version = "2.0.0"
edition = "2021"
authors = ["malik <aremumalik05@gmail.com>", "Shuhui Luo <twitter.com/aureliano_law>"]
description = "The Uniswap SDK Core in Rust provides essential functionality for interacting with the Uniswap decentralized exchange"
Expand Down
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ pub enum Rounding {
lazy_static! {
/// Represents the maximum amount contained in a uint256
pub static ref MAX_UINT256: BigInt =
BigInt::from_bytes_be(Sign::Plus, &U256::MAX.to_be_bytes::<32>());
BigInt::from_biguint(Sign::Plus, BigUint::from_bytes_le(&U256::MAX.as_le_bytes()));
}
17 changes: 11 additions & 6 deletions src/entities/base_currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,34 +31,39 @@ pub trait BaseCurrency: Clone {
fn decimals(&self) -> u8;

/// The symbol of the currency, i.e. a short textual non-unique identifier
fn symbol(&self) -> Option<String>;
fn symbol(&self) -> Option<&String>;

/// The name of the currency, i.e. a descriptive textual non-unique identifier
fn name(&self) -> Option<String>;
fn name(&self) -> Option<&String>;
}

impl<M: Clone> BaseCurrency for CurrencyLike<M> {
#[inline]
fn chain_id(&self) -> ChainId {
self.chain_id
}

#[inline]
fn decimals(&self) -> u8 {
self.decimals
}

fn symbol(&self) -> Option<String> {
self.symbol.clone()
#[inline]
fn symbol(&self) -> Option<&String> {
self.symbol.as_ref()
}

fn name(&self) -> Option<String> {
self.name.clone()
#[inline]
fn name(&self) -> Option<&String> {
self.name.as_ref()
}
}

/// Implement [`Deref`] to allow direct access to the metadata of the currency
impl<M> Deref for CurrencyLike<M> {
type Target = M;

#[inline]
fn deref(&self) -> &Self::Target {
&self.meta
}
Expand Down
6 changes: 6 additions & 0 deletions src/entities/ether.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ pub type Ether = CurrencyLike<()>;

impl Currency for Ether {
/// Checks if the currency is native to the blockchain.
#[inline]
fn is_native(&self) -> bool {
true
}

/// Retrieves the address associated with the currency.
#[inline]
fn address(&self) -> Address {
self.wrapped().address()
}

/// Checks if the currency is equal to another currency.
#[inline]
fn equals(&self, other: &impl Currency) -> bool {
match other.is_native() {
true => self.chain_id() == other.chain_id(),
Expand All @@ -24,6 +27,7 @@ impl Currency for Ether {
}

/// Returns the wrapped token representation of the currency.
#[inline]
fn wrapped(&self) -> Token {
match WETH9::default().get(self.chain_id()) {
Some(weth9) => weth9.clone(),
Expand All @@ -34,6 +38,7 @@ impl Currency for Ether {

impl Ether {
/// Creates a new instance of [`Ether`] with the specified chain ID.
#[inline]
pub fn new(chain_id: u64) -> Self {
Self {
chain_id,
Expand All @@ -45,6 +50,7 @@ impl Ether {
}

/// Retrieves or creates an [`Ether`] instance for the specified chain ID.
#[inline]
pub fn on_chain(chain_id: u64) -> Self {
Self::new(chain_id)
}
Expand Down
41 changes: 24 additions & 17 deletions src/entities/fractions/currency_amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct CurrencyMeta<T: Currency> {

impl<T: Currency> CurrencyAmount<T> {
/// Constructor method for creating a new currency amount
#[inline]
fn new(
currency: T,
numerator: impl Into<BigInt>,
Expand All @@ -23,7 +24,7 @@ impl<T: Currency> CurrencyAmount<T> {
let numerator = numerator.into();
let denominator = denominator.into();
// Ensure the amount does not exceed MAX_UINT256
if !numerator.div_floor(&denominator).le(&MAX_UINT256) {
if numerator.div_floor(&denominator) > *MAX_UINT256 {
return Err(Error::MaxUint);
}
let exponent = currency.decimals();
Expand All @@ -38,11 +39,13 @@ impl<T: Currency> CurrencyAmount<T> {
}

/// Returns a new currency amount instance from the unitless amount of token (raw amount)
#[inline]
pub fn from_raw_amount(currency: T, raw_amount: impl Into<BigInt>) -> Result<Self, Error> {
Self::new(currency, raw_amount, 1)
}

/// Construct a currency amount with a denominator that is not equal to 0
#[inline]
pub fn from_fractional_amount(
currency: T,
numerator: impl Into<BigInt>,
Expand All @@ -52,59 +55,61 @@ impl<T: Currency> CurrencyAmount<T> {
}

/// Multiplication of currency amount by another fractional amount
pub fn multiply<M>(&self, other: &impl FractionBase<M>) -> Result<Self, Error> {
#[inline]
pub fn multiply<M: Clone>(&self, other: &impl FractionBase<M>) -> Result<Self, Error> {
let multiplied = self.as_fraction() * other.as_fraction();
Self::from_fractional_amount(
self.currency.clone(),
multiplied.numerator(),
multiplied.denominator(),
multiplied.numerator,
multiplied.denominator,
)
}

/// Division of currency amount by another fractional amount
pub fn divide<M>(&self, other: &impl FractionBase<M>) -> Result<Self, Error> {
#[inline]
pub fn divide<M: Clone>(&self, other: &impl FractionBase<M>) -> Result<Self, Error> {
let divided = self.as_fraction() / other.as_fraction();
Self::from_fractional_amount(
self.currency.clone(),
divided.numerator(),
divided.denominator(),
divided.numerator,
divided.denominator,
)
}

/// Convert the currency amount to a string with exact precision
#[inline]
pub fn to_exact(&self) -> String {
BigDecimal::from(self.quotient())
.div(BigDecimal::from(BigInt::from(self.decimal_scale.clone())))
.to_string()
}

/// Addition of another currency amount to the current amount
#[inline]
pub fn add(&self, other: &Self) -> Result<Self, Error> {
if !self.currency.equals(&other.currency) {
return Err(Error::NotEqual);
}
let added = self.as_fraction() + other.as_fraction();
Self::from_fractional_amount(
self.currency.clone(),
added.numerator(),
added.denominator(),
)
Self::from_fractional_amount(self.currency.clone(), added.numerator, added.denominator)
}

/// Subtraction of another currency amount from the current amount
#[inline]
pub fn subtract(&self, other: &Self) -> Result<Self, Error> {
if !self.currency.equals(&other.currency) {
return Err(Error::NotEqual);
}
let subtracted = self.as_fraction() - other.as_fraction();
Self::from_fractional_amount(
self.currency.clone(),
subtracted.numerator(),
subtracted.denominator(),
subtracted.numerator,
subtracted.denominator,
)
}

/// Convert the currency amount to a string with a specified number of significant digits
#[inline]
pub fn to_significant(
&self,
significant_digits: u8,
Expand All @@ -115,6 +120,7 @@ impl<T: Currency> CurrencyAmount<T> {
}

/// Convert the currency amount to a string with a fixed number of decimal places
#[inline]
pub fn to_fixed(&self, decimal_places: u8, rounding: Rounding) -> Result<String, Error> {
if decimal_places > self.currency.decimals() {
return Err(Error::NotEqual);
Expand All @@ -132,11 +138,12 @@ impl<T: Currency> CurrencyAmount<T> {
}

/// Wrap the currency amount if the currency is not native
#[inline]
pub fn wrapped(&self) -> Result<CurrencyAmount<Token>, Error> {
CurrencyAmount::from_fractional_amount(
self.currency.wrapped(),
self.numerator(),
self.denominator(),
self.numerator().clone(),
self.denominator().clone(),
)
}
}
Expand Down Expand Up @@ -205,7 +212,7 @@ mod tests {
let numerator: BigInt = MAX_UINT256.clone() + 2;
let amount =
CurrencyAmount::from_fractional_amount(TOKEN18.clone(), numerator.clone(), 2).unwrap();
assert_eq!(amount.numerator(), numerator);
assert_eq!(amount.numerator(), &numerator);
}

#[test]
Expand Down
Loading

0 comments on commit 15f1d3d

Please sign in to comment.