jaemk / cached

Rust cache structures and easy function memoization
MIT License
1.58k stars 95 forks source link

Interoperability with smartstring #95

Closed jqnatividad closed 2 years ago

jqnatividad commented 3 years ago

First off, thanks for this library. The payoff was immediate, as it doubled the performance of the geocoder I was using.

As my keys are relatively short (lat/long coordinate), I was wondering if cached can work with smartstring (https://docs.rs/smartstring/0.2.9/smartstring/) to further increase performance.

jaemk commented 3 years ago

Hey @jqnatividad , glad to hear! By "work with smartstring" do you mean accept and return SmartStrings? That should work since SmartString impls Eq and Clone - I added a test just to be sure https://github.com/jaemk/cached/blob/848050737f227223adf2475d79dbc61bd1bd91c3/tests/cached.rs#L901

Or were you thinking something else?

jqnatividad commented 3 years ago

Whoa! That was fast! (pun intended) :)

Thanks for adding the smartsting test! And yes, I meant working and accepting SmartStrings.

I'll try it with my project and report back my findings.

jaemk commented 3 years ago

Nice! There's also some flexibility if you want your cache key to be a SmartString constructed from something else using key to specify the cache key type and convert to pass a code block for constructing a value of that type from the function arguments. See this example https://github.com/jaemk/cached/blob/848050737f227223adf2475d79dbc61bd1bd91c3/examples/kitchen_sink_proc_macro.rs#L67

Would let you do something like

 #[cached(
     key = "smarstring::alias::String",
     convert = r#"{ smartstring::alias::String::from(lat_long) }"#
 )] 
 fn search(lat_long: &str) -> Vec<Place> { ... }
jqnatividad commented 2 years ago

In my initial implementation, using the constructed smartstring key approach you outlined above, I'm sad to report that it actually resulted in 30% slower performance in geocoding 1M rows with a 49.58% cache hit rate).

That is, from:

#[cached(
    key = "String",
    convert = r#"{ format!("{}{}", lat_long, formatstr) }"#,
    size = 500_000
    option = true
)]
fn search_cached(lat_long: &str, formatstr: &str) -> Option<String> {

to

#[cached(
    key = "smartstring::alias::String",
    convert = r#"{ smartstring::alias::String::from(format!("{}{}", lat_long, formatstr)) }"#,
    size = 500_000
    option = true
)]
fn search_cached(lat_long: &str, formatstr: &str) -> Option<String> {

Perhaps, I'll need to use smartstring natively to get better results.... I'll try that and report back...

jqnatividad commented 2 years ago

Closing this as we now have interoperability with smartstring, though in my use case, it actually resulted in lower performance.