From 2eefaef0ae74724bda5857476fc39af28040e36d Mon Sep 17 00:00:00 2001 From: Avril Date: Sun, 20 Sep 2020 00:46:25 +0100 Subject: [PATCH] small update --- Cargo.toml | 7 +++++-- README.md | 10 ++++++---- build.rs | 24 ++++++++++++++++++++++++ src/lib.rs | 48 ++++++++++++++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index d2ef0a2..861b35d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,12 @@ [package] name = "smallmap" +description = "Small byte-sized generic key-value map type" +keywords = ["map", "table", "small", "key", "value"] version = "0.1.0" authors = ["Avril "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] + +[build-dependencies] +rustc_version = "0.2" diff --git a/README.md b/README.md index ec0952d..3aace81 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # smallmap -A small byte sized table map. +A small byte sized table map. (Currently *requires* nightly). -Designed for instances where you want a map with small keys (e.g. primitive). +Designed for instances where you want a small map with relatively trivial keys (e.g. primitive type). Performance greately outpaces hash-based maps in these cases. + + # Benchmarks Some rudamentary benchmarks @@ -18,10 +20,10 @@ Some rudamentary benchmarks | Which | ns/iter | |-----------------|---------| -| `HashMap` | 126,418 | +| `HashMap` | 65,418 | | `smallmap::Map` | 9,416 | -## u8 +## u8 (single table) | Which | ns/iter | |-----------------|---------| | `HashMap` | 15 | diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6399463 --- /dev/null +++ b/build.rs @@ -0,0 +1,24 @@ + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + match version_meta().unwrap().channel { + Channel::Stable => { + println!("cargo:rustc-cfg=stable"); + } + Channel::Beta => { + println!("cargo:rustc-cfg=beta"); + } + Channel::Nightly => { + println!("cargo:rustc-cfg=nightly"); + } + Channel::Dev => { + println!("cargo:rustc-cfg=dev"); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 3ed47ae..8fada16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,11 @@ #![feature(const_in_array_repeat_expressions)] #![feature(const_fn)] -#![feature(test)] +#![cfg_attr(nightly, feature(test))] + #![allow(dead_code)] -extern crate test; +#[cfg(nightly)] extern crate test; const MAX: usize = 256; @@ -186,6 +187,24 @@ where K: Collapsible } None } + + + pub fn remove(&mut self, key: &Q) -> Option + where K: Borrow, + Q: Collapsible + Eq + { + for page in self.0.iter_mut() + { + let v = page.search_mut(key); + match v { + Some((ref ok, _)) if key.eq(ok.borrow()) => { + return v.take().map(|(_, v)| v); + }, + _ => (), + } + } + None + } pub fn insert(&mut self, key: K, value: V) -> Option { @@ -251,7 +270,7 @@ pub fn collapse>(bytes: T) -> u8 mod tests { use super::*; - use test::{Bencher, black_box}; + #[cfg(nightly)] use test::{Bencher, black_box}; #[test] fn it_works() @@ -276,7 +295,7 @@ mod tests let mut small = Map::new(); let mut hash = HashMap::new(); - let input = r#"Bludgeoning clsql and mariadb until they kind of work + let input = r#"こんばんわBludgeoning clsql and mariadb until they kind of work There are no good mysql connectors for Common Lisp, whatever you decide to use, you're not going to have a good time. clsql is pretty much the best we've got, and since I had such a delightful experience configuring it myself, I hope to smooth the process of getting this shitware up and running with my own little blogpost here. connecting to a database @@ -397,6 +416,7 @@ Now the charset for our initial connection should be set to utf8, and we're free assert_eq!(&op1[..], &op2[..]); } + #[cfg(nightly)] #[bench] fn char_smallmap(b: &mut Bencher) { @@ -421,7 +441,7 @@ stream"#.chars().collect(); } }) } - + #[cfg(nightly)] #[bench] fn u8_smallmap(b: &mut Bencher) { @@ -439,7 +459,8 @@ stream"#.chars().collect(); } use std::collections::HashMap; - + + #[cfg(nightly)] #[bench] fn char_map(b: &mut Bencher) { @@ -465,6 +486,7 @@ stream"#.chars().collect(); }) } + #[cfg(nightly)] #[bench] fn u8_map(b: &mut Bencher) { @@ -480,13 +502,13 @@ stream"#.chars().collect(); } }) } - + #[cfg(nightly)] #[bench] fn smap_bench(b: &mut Bencher) { let mut small = Map::new(); - let input = r#"Bludgeoning clsql and mariadb until they kind of work + let input = r#"こんばんわBludgeoning clsql and mariadb until they kind of work There are no good mysql connectors for Common Lisp, whatever you decide to use, you're not going to have a good time. clsql is pretty much the best we've got, and since I had such a delightful experience configuring it myself, I hope to smooth the process of getting this shitware up and running with my own little blogpost here. connecting to a database @@ -595,12 +617,13 @@ Now the charset for our initial connection should be set to utf8, and we're free } }) } + #[cfg(nightly)] #[bench] fn hmap_bench(b: &mut Bencher) { let mut small = HashMap::new(); - let input = r#"Bludgeoning clsql and mariadb until they kind of work + let input = r#"こんばんわBludgeoning clsql and mariadb until they kind of work There are no good mysql connectors for Common Lisp, whatever you decide to use, you're not going to have a good time. clsql is pretty much the best we've got, and since I had such a delightful experience configuring it myself, I hope to smooth the process of getting this shitware up and running with my own little blogpost here. connecting to a database @@ -701,11 +724,8 @@ Now the charset for our initial connection should be set to utf8, and we're free b.iter(|| { for ch in input.chars() { - if !small.contains_key(&ch) { - small.insert(ch, 0); - } else { - *small.get_mut(&ch).unwrap() += 1; - } + let counter = small.entry(ch).or_insert(0); + *counter +=1; } }) }