Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LRU statement cache #61

Closed
wants to merge 39 commits into from
Closed

LRU statement cache #61

wants to merge 39 commits into from

Conversation

gwenn
Copy link
Collaborator

@gwenn gwenn commented Aug 2, 2015

No description provided.

/// # Failure
///
/// Will return `Err` if no cached statement can be found and the underlying SQLite prepare call fails.
pub fn get(&mut self, sql: &str) -> Result<Statement<'conn>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to think this should return a Result<CachedStatement<'cache>>. CachedStatement would wrap up Statement (and implement Deref/DerefMut for it too, I think), and would return it to the cache in drop. This would remove the need to remember to call release. We could actually remove release altogether, I think, and add a release or discard method to CachedStatement that would (a) take self (to consume it) and (b) set a flag (or something similar) to avoid returning the statement to the cache in drop.

What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, introducing a CachedStatement is the right way.

@gwenn
Copy link
Collaborator Author

gwenn commented Dec 16, 2015

I am sorry to bother you but I cannot make the CachedStatement work: FIXME cannot borrow immutable borrowed content*self.cacheas mutable.
Should I introduce a RefCell?

@jgallagher
Copy link
Contributor

Good news / bad news. Good news is you can get around the issues in drop by putting the statement inside an Option (which we'll guarantee is always Some() and is therefore safe to call .unwrap() on), so you can .take() the value out during destruction:

pub struct CachedStatement<'conn> {
    stmt: Option<Statement<'conn>>,
    cache: RefCell<StatementCache<'conn>>,
    pub cacheable : bool,
}

impl<'conn> Drop for CachedStatement<'conn> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if self.cacheable {
            self.cache.borrow_mut().release(self.stmt.take().unwrap(), false);
        } else {
            self.stmt.take().unwrap().finalize();
        }
    }
}

Bad news is it looks like lru-cache doesn't work on stable or beta rust. It depends on linked-hash-map which uses an unstable feature. I don't think we can merge this in and keep rusqlite usable on stable rust. :(

@gwenn
Copy link
Collaborator Author

gwenn commented Dec 17, 2015

Thanks.
This one works on stable but the Value must be clonable and it cannot be cleared...

@gwenn
Copy link
Collaborator Author

gwenn commented Dec 17, 2015

I will need your help: how to create a RefCell from a reference ?

src/cache.rs:78         stmt.map(|stmt| CachedStatement::new(stmt, RefCell::new(self)))

@jgallagher
Copy link
Contributor

Mm, that's never going to work - if it did, you'd end up with multiple &mut StatementCaches in each statement, which should be impossible.

What if you put the internal cache itself inside a RefCell? Then get and release could take &self (they could borrow_mut() the underlying storage), and CachedStatement could hold a plain &'a StatementCache?

@gwenn
Copy link
Collaborator Author

gwenn commented Dec 19, 2015

The implementation is not perfect but it seems to be working...
I will try to make some benches to show the difference between cache and no cache.

@gwenn
Copy link
Collaborator Author

gwenn commented Dec 20, 2015

test bench_cache ... bench: 124 ns/iter (+/- 76)
test bench_no_cache ... bench: 5,538 ns/iter (+/- 4,178)

@jgallagher
Copy link
Contributor

Merged as part of #113.

@jgallagher jgallagher closed this May 19, 2016
@gwenn gwenn deleted the stmt-cache branch May 19, 2016 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants