changeset 25:0fa95071021c

Convert all Iterator/LdbIterator types to use slices efficiency yay!
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 12 Jun 2016 11:02:33 +0200
parents cc51ccd8970c
children d54a08be9b8a
files src/memtable.rs src/skipmap.rs src/types.rs
diffstat 3 files changed, 60 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/src/memtable.rs	Sun Jun 12 11:01:45 2016 +0200
+++ b/src/memtable.rs	Sun Jun 12 11:02:33 2016 +0200
@@ -118,13 +118,13 @@
         buf
     }
 
-    /// Parses a memtable key and returns (keylen, key, tag, vallen, val).
-    /// If the key only contains (keylen, key, tag), the vallen and val return values will be
+    /// Parses a memtable key and returns  (keylen, key offset, tag, vallen, val offset).
+    /// If the key only contains (keylen, key, tag), the vallen and val offset return values will be
     /// meaningless.
-    fn parse_memtable_key(mkey: &Vec<u8>) -> (usize, Vec<u8>, u64, usize, Vec<u8>) {
+    fn parse_memtable_key(mkey: &[u8]) -> (usize, usize, u64, usize, usize) {
         let (keylen, mut i): (usize, usize) = VarInt::decode_var(&mkey);
 
-        let key = mkey[i..i + keylen].to_vec();
+        let keyoff = i;
         i += keylen;
 
         if mkey.len() > i {
@@ -132,13 +132,14 @@
             i += 8;
 
             let (vallen, j): (usize, usize) = VarInt::decode_var(&mkey[i..]);
+
+            let valoff = i + j;
+
             i += j;
 
-            let val = mkey[i..].to_vec();
-
-            return (keylen, key, tag, vallen, val);
+            return (keylen, keyoff, tag, vallen, valoff);
         } else {
-            return (keylen, key, 0, 0, Vec::new());
+            return (keylen, keyoff, 0, 0, 0);
         }
     }
 
@@ -149,12 +150,13 @@
 
         if iter.valid() {
             let foundkey = iter.current().0;
-            let (lkeylen, lkey, _, _, _) = Self::parse_memtable_key(key.memtable_key());
-            let (fkeylen, fkey, tag, vallen, val) = Self::parse_memtable_key(foundkey);
+            let (lkeylen, lkeyoff, _, _, _) = Self::parse_memtable_key(key.memtable_key());
+            let (fkeylen, fkeyoff, tag, vallen, valoff) = Self::parse_memtable_key(foundkey);
 
-            if C::cmp(&lkey, &fkey) == Ordering::Equal {
+            if C::cmp(&key.memtable_key()[lkeyoff..lkeyoff + lkeylen],
+                      &foundkey[fkeyoff..fkeyoff + fkeylen]) == Ordering::Equal {
                 if tag & 0xff == ValueType::TypeValue as u64 {
-                    return Result::Ok(val);
+                    return Result::Ok(foundkey[valoff..valoff + vallen].to_vec());
                 } else {
                     return Result::Err(Status::NotFound(String::new()));
                 }
@@ -177,15 +179,17 @@
 }
 
 impl<'a, C: 'a + Comparator> Iterator for MemtableIterator<'a, C> {
-    type Item = (Vec<u8>, Vec<u8>);
+    type Item = (&'a [u8], &'a [u8]);
 
     fn next(&mut self) -> Option<Self::Item> {
         loop {
             if let Some((foundkey, _)) = self.skipmapiter.next() {
-                let (_, key, tag, _, val) = MemTable::<C>::parse_memtable_key(foundkey);
+                let (keylen, keyoff, tag, vallen, valoff) =
+                    MemTable::<C>::parse_memtable_key(foundkey);
 
                 if tag & 0xff == ValueType::TypeValue as u64 {
-                    return Some((key, val));
+                    return Some((&foundkey[keyoff..keyoff + keylen],
+                                 &foundkey[valoff..valoff + vallen]));
                 } else {
                     continue;
                 }
@@ -200,14 +204,14 @@
     fn valid(&self) -> bool {
         self.skipmapiter.valid()
     }
-    fn current(&self) -> Self::Item {
+    fn current(&'a self) -> Self::Item {
         assert!(self.valid());
 
-        let (foundkey, _) = self.skipmapiter.current();
-        let (_, key, tag, _, val) = MemTable::<C>::parse_memtable_key(foundkey);
+        let (foundkey, _): (&'a [u8], &'a [u8]) = self.skipmapiter.current();
+        let (keylen, keyoff, tag, vallen, valoff) = MemTable::<C>::parse_memtable_key(foundkey);
 
         if tag & 0xff == ValueType::TypeValue as u64 {
-            return (key, val);
+            return (&foundkey[keyoff..keyoff + keylen], &foundkey[valoff..valoff + vallen]);
         } else {
             panic!("should not happen");
         }
@@ -249,7 +253,7 @@
                &"123".as_bytes().to_vec());
 
         assert_eq!(mt.map.iter().next().unwrap().0,
-                   &vec![3, 97, 98, 99, 1, 123, 0, 0, 0, 0, 0, 0, 3, 49, 50, 51]);
+                   vec![3, 97, 98, 99, 1, 123, 0, 0, 0, 0, 0, 0, 3, 49, 50, 51].as_slice());
     }
 
     #[test]
@@ -269,6 +273,7 @@
         }
 
         if let Result::Ok(v) = mt.get(&LookupKey::new(&"abc".as_bytes().to_vec(), 124)) {
+            println!("{:?}", v);
             panic!("found");
         }
     }
@@ -282,23 +287,23 @@
 
         iter.next();
         assert!(iter.valid());
-        assert_eq!(iter.current().0, vec![97, 98, 99]);
-        assert_eq!(iter.current().1, vec![49, 50, 51]);
+        assert_eq!(iter.current().0, vec![97, 98, 99].as_slice());
+        assert_eq!(iter.current().1, vec![49, 50, 51].as_slice());
 
         iter.seek(&"abf".as_bytes().to_vec());
-        assert_eq!(iter.current().0, vec![97, 98, 102]);
-        assert_eq!(iter.current().1, vec![49, 50, 54]);
+        assert_eq!(iter.current().0, vec![97, 98, 102].as_slice());
+        assert_eq!(iter.current().1, vec![49, 50, 54].as_slice());
     }
 
     #[test]
     fn test_parse_memtable_key() {
         let key = vec![3, 1, 2, 3, 1, 123, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6];
-        let (keylen, key, tag, vallen, val) =
+        let (keylen, keyoff, tag, vallen, valoff) =
             MemTable::<StandardComparator>::parse_memtable_key(&key);
         assert_eq!(keylen, 3);
-        assert_eq!(key, vec![1, 2, 3]);
+        assert_eq!(&key[keyoff..keyoff + keylen], vec![1, 2, 3].as_slice());
         assert_eq!(tag, 123 << 8 | 1);
         assert_eq!(vallen, 3);
-        assert_eq!(val, vec![4, 5, 6]);
+        assert_eq!(&key[valoff..valoff + vallen], vec![4, 5, 6].as_slice());
     }
 }
--- a/src/skipmap.rs	Sun Jun 12 11:01:45 2016 +0200
+++ b/src/skipmap.rs	Sun Jun 12 11:02:33 2016 +0200
@@ -11,13 +11,13 @@
 /// Trait used to influence how SkipMap determines the order of elements. Use StandardComparator
 /// for the normal implementation using numerical comparison.
 pub trait Comparator {
-    fn cmp(&Vec<u8>, &Vec<u8>) -> Ordering;
+    fn cmp(&[u8], &[u8]) -> Ordering;
 }
 
 pub struct StandardComparator;
 
 impl Comparator for StandardComparator {
-    fn cmp(a: &Vec<u8>, b: &Vec<u8>) -> Ordering {
+    fn cmp(a: &[u8], b: &[u8]) -> Ordering {
         a.cmp(b)
     }
 }
@@ -230,6 +230,20 @@
     current: *const Node,
 }
 
+impl<'a, C: Comparator + 'a> Iterator for SkipMapIter<'a, C> {
+    type Item = (&'a [u8], &'a [u8]);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        // we first go to the next element, then return that -- in order to skip the head node
+        unsafe {
+            (*self.current).next.as_ref().map(|next| {
+                self.current = transmute_copy(&next.as_ref());
+                ((*self.current).key.as_slice(), (*self.current).value.as_slice())
+            })
+        }
+    }
+}
+
 impl<'a, C: Comparator> LdbIterator<'a> for SkipMapIter<'a, C> {
     fn seek(&mut self, key: &Vec<u8>) {
         let node = self.map.get_greater_or_equal(key);
@@ -238,26 +252,12 @@
     fn valid(&self) -> bool {
         unsafe { !(*self.current).key.is_empty() }
     }
-    fn current(&'a self) -> (&'a Vec<u8>, &'a Vec<u8>) {
+    fn current(&'a self) -> Self::Item {
         assert!(self.valid());
         unsafe { (&(*self.current).key, &(*self.current).value) }
     }
 }
 
-impl<'a, C: Comparator + 'a> Iterator for SkipMapIter<'a, C> {
-    type Item = (&'a Vec<u8>, &'a Vec<u8>);
-
-    fn next(&mut self) -> Option<Self::Item> {
-        // we first go to the next element, then return that -- in order to skip the head node
-        unsafe {
-            (*self.current).next.as_ref().map(|next| {
-                self.current = transmute_copy(&next.as_ref());
-                (&(*self.current).key, &(*self.current).value)
-            })
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -345,12 +345,10 @@
         iter.next();
         assert!(iter.valid());
         iter.seek(&"abz".as_bytes().to_vec());
-        assert_eq!(iter.current(),
-                   (&"abz".as_bytes().to_vec(), &"def".as_bytes().to_vec()));
+        assert_eq!(iter.current(), ("abz".as_bytes(), "def".as_bytes()));
         // go back to beginning
         iter.seek(&"aba".as_bytes().to_vec());
-        assert_eq!(iter.current(),
-                   (&"aba".as_bytes().to_vec(), &"def".as_bytes().to_vec()));
+        assert_eq!(iter.current(), ("aba".as_bytes(), "def".as_bytes()));
 
         iter.seek(&"".as_bytes().to_vec());
         assert!(iter.valid());
--- a/src/types.rs	Sun Jun 12 11:01:45 2016 +0200
+++ b/src/types.rs	Sun Jun 12 11:02:33 2016 +0200
@@ -22,6 +22,10 @@
 /// An extension of the standard `Iterator` trait that supports some methods necessary for LevelDB.
 /// This works because the iterators used are stateful and keep the last returned element.
 pub trait LdbIterator<'a>: Iterator {
+    // We're emulating LevelDB's Slice type here using actual slices with the lifetime of the
+    // iterator. The lifetime of the iterator is usually the one of the backing storage (Block,
+    // MemTable, SkipMap...)
+    //type Item = (&'a [u8], &'a [u8]);
     fn seek(&mut self, key: &Vec<u8>);
     fn valid(&self) -> bool;
     fn current(&'a self) -> Self::Item;
@@ -56,7 +60,11 @@
 
 impl SnapshotList {
     pub fn new() -> SnapshotList {
-        SnapshotList { map: HashMap::new(), newest: 0, oldest: 0 }
+        SnapshotList {
+            map: HashMap::new(),
+            newest: 0,
+            oldest: 0,
+        }
     }
 
     pub fn new_snapshot(&mut self, seq: SequenceNumber) -> Snapshot {
@@ -91,7 +99,6 @@
     pub fn empty(&self) -> bool {
         self.oldest == 0
     }
-
 }
 
 #[cfg(test)]