Use a real LruCache instead of a VecDeque.

This commit is contained in:
John Gallagher 2016-05-17 12:26:17 -05:00
parent 20b93bdb96
commit d923d8c670
3 changed files with 15 additions and 22 deletions

View File

@ -22,6 +22,7 @@ trace = []
[dependencies]
time = "~0.1.0"
bitflags = "0.7"
lru-cache = "0.0.7"
libc = "~0.2"
clippy = {version = "~0.0.58", optional = true}
chrono = { version = "~0.2", optional = true }

View File

@ -1,8 +1,8 @@
//! Prepared statements cache for faster execution.
use std::cell::RefCell;
use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use lru_cache::LruCache;
use {Result, Connection, Statement};
use raw_statement::RawStatement;
@ -40,9 +40,7 @@ impl Connection {
/// Prepared statements LRU cache.
#[derive(Debug)]
pub struct StatementCache {
cache: RefCell<VecDeque<RawStatement>>, // back = LRU
}
pub struct StatementCache(RefCell<LruCache<String, RawStatement>>);
/// Cacheable statement.
///
@ -92,7 +90,7 @@ impl<'conn> CachedStatement<'conn> {
impl StatementCache {
/// Create a statement cache.
pub fn with_capacity(capacity: usize) -> StatementCache {
StatementCache { cache: RefCell::new(VecDeque::with_capacity(capacity)) }
StatementCache(RefCell::new(LruCache::new(capacity)))
}
/// Search the cache for a prepared-statement object that implements `sql`.
@ -106,27 +104,20 @@ impl StatementCache {
conn: &'conn Connection,
sql: &str)
-> Result<CachedStatement<'conn>> {
let mut cache = self.cache.borrow_mut();
let stmt = match cache.iter()
.rposition(|entry| entry.sql().to_bytes().eq(sql.as_bytes())) {
Some(index) => {
let raw_stmt = cache.swap_remove_front(index).unwrap(); // FIXME Not LRU compliant
Ok(Statement::new(conn, raw_stmt))
}
_ => conn.prepare(sql),
let mut cache = self.0.borrow_mut();
let stmt = match cache.remove(sql) {
Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
None => conn.prepare(sql),
};
stmt.map(|stmt| CachedStatement::new(stmt, self))
}
// Return a statement to the cache.
fn cache_stmt(&self, stmt: RawStatement) {
let mut cache = self.cache.borrow_mut();
if cache.capacity() == cache.len() {
// is full
cache.pop_back(); // LRU dropped
}
let mut cache = self.0.borrow_mut();
stmt.clear_bindings();
cache.push_front(stmt)
let sql = String::from_utf8_lossy(stmt.sql().to_bytes()).to_string();
cache.insert(sql, stmt);
}
}
@ -137,15 +128,15 @@ mod test {
impl StatementCache {
fn clear(&self) {
self.cache.borrow_mut().clear();
self.0.borrow_mut().clear();
}
fn len(&self) -> usize {
self.cache.borrow().len()
self.0.borrow().len()
}
fn capacity(&self) -> usize {
self.cache.borrow().capacity()
self.0.borrow().capacity()
}
}

View File

@ -55,6 +55,7 @@
extern crate libc;
extern crate libsqlite3_sys as ffi;
extern crate lru_cache;
#[macro_use]
extern crate bitflags;
#[cfg(test)]