Warp: trying not to clone a string (hacktoberfest opportunity!)

I'm using warp as a simple proxy, and caching the string I'm proxying for 10s. I'd love to reduce waste in this 10s window and have my string not get cloned(). In my benchmarking, I think these allocations are the thing dragging me down (but it could also be my locking, I tried a RwLock implementation but didn't see much performance gain).

I've laid out the code at this issue. And I'll paste the troubling section here just for a taste:

// read from cache if it's still valid, otherwise hit the URL + write
fn cache_visit(cache: Store) -> impl warp::Reply {
    let mut timed_string = cache.lock().unwrap();
    if Instant::now() > timed_string.time {
        timed_string.time = Instant::now() + Duration::from_secs(10);
        timed_string.text = reqwest::get(&timed_string.url).unwrap().text().unwrap();
    }
    timed_string.text.clone()
}

edit: forgot to say, I'd be up for merging someone's solution to this, if it's easier to code it out and open a PR on the linked repo! This would get you a hacktoberfest PR too, in case anyone is doing that.

Have you gotten any response to this on your github issue or reddit post? I am very interested in this problem as I spent two days this weekend trying to solve it and came up empty.

Yes! I just got it working after getting a hint from the Warp maintainer (in this thread): Use Bytes from the bytes crate -- and I found you can construct the warp-compatible response with:

warp::http::Response::new(bytes_obj.clone())

You can follow the chain of links in my original comment. Or at some point later today I'll have my prototype on github and working fully. :soon:

edit: the Bytes is a reference-counting pointer, so .clone() on it only clones the reference, not the underlying chunk of memory like String#clone()

1 Like

related code change over here (lots of unwrap() in here to get rid of still, but the efficiency level is at peak! ...I think): https://github.com/jakswa/warp_proxy/commit/ce82d900b7f5b140d4b43a502752acd9b77cd302

hmm. So there was no way to get around having to clone() the data, you just have to use a data structure that is cheaper than String. Did you try the newtype technique he suggested to see if that would require cloning? I might have a go at that when I get home.

I'd definitely be curious to hear about more efficient options. To be clear bytes.clone() is cloning a reference/pointer. Depending on string size (mine were 10s of kBs), that's way cheaper than cloning the underlying string? It's only my impression. I have verified anecdotal memory differences with local benchmarking. It seems to perform as advertised.

You are correct about the difference between cloning the data versus cloning a pointer to the data, but I was just wondering if there was a way to manage mutability within the bounds of ownership for Mutex-wrapped data. It seems not.