From f9e2c68cd0256b7adc27e9804c9befc528c69f1e Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy <mmstickman@gmail.com> Date: Fri, 14 Apr 2017 11:14:52 -0400 Subject: [PATCH] Use FNV-based Hash Maps --- Cargo.toml | 6 ++++++ src/builtins/functions.rs | 6 +++--- src/builtins/mod.rs | 8 ++++---- src/builtins/variables.rs | 4 ++-- src/main.rs | 6 ++++++ src/parser/mod.rs | 2 +- src/parser/shell_expand/mod.rs | 4 ++-- src/shell/assignments.rs | 6 +++--- src/shell/mod.rs | 14 ++++++++------ src/variables.rs | 12 ++++++------ 10 files changed, 41 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71033d8a..008532a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ build = "build.rs" name = "ion" [dependencies] +fnv = "1.0" glob = "0.2" liner = "0.1.4" peg-syntax-ext = "0.4" @@ -30,3 +31,8 @@ users = "0.5.1" [build-dependencies] ansi_term = "0.9" version_check = "0.1" + +[profile.release] +# debug = true +# rustflags = [ "-C", "target-cpu=native"] +# lto = true diff --git a/src/builtins/functions.rs b/src/builtins/functions.rs index 0ec64634..69d53e51 100644 --- a/src/builtins/functions.rs +++ b/src/builtins/functions.rs @@ -1,9 +1,9 @@ use flow_control::{Function}; -use std::collections::HashMap; +use fnv::FnvHashMap; use status::*; use std::io::{self, Write}; -fn print_functions(functions: &HashMap<String, Function>) { +fn print_functions(functions: &FnvHashMap<String, Function>) { let stdout = io::stdout(); let stdout = &mut stdout.lock(); @@ -13,7 +13,7 @@ fn print_functions(functions: &HashMap<String, Function>) { } } -pub fn fn_(functions: &mut HashMap<String, Function>) -> i32 +pub fn fn_(functions: &mut FnvHashMap<String, Function>) -> i32 { print_functions(functions); SUCCESS diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index e6459b14..be1cd9a6 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -6,7 +6,7 @@ use self::variables::{alias, drop_alias, drop_variable, export_variable}; use self::functions::fn_; use self::source::source; -use std::collections::HashMap; +use fnv::FnvHashMap; use std::io::{self, Write}; use std::process; @@ -35,8 +35,8 @@ pub struct Builtin { impl Builtin { /// Return the map from command names to commands - pub fn map() -> HashMap<&'static str, Self> { - let mut commands: HashMap<&str, Self> = HashMap::new(); + pub fn map() -> FnvHashMap<&'static str, Self> { + let mut commands: FnvHashMap<&str, Self> = FnvHashMap::with_capacity_and_hasher(32, Default::default()); /* Directories */ commands.insert("cd", @@ -230,7 +230,7 @@ impl Builtin { }, }); - let command_helper: HashMap<&'static str, &'static str> = commands.iter() + let command_helper: FnvHashMap<&'static str, &'static str> = commands.iter() .map(|(k, v)| { (*k, v.help) }) diff --git a/src/builtins/variables.rs b/src/builtins/variables.rs index 78060902..b6246a18 100644 --- a/src/builtins/variables.rs +++ b/src/builtins/variables.rs @@ -1,13 +1,13 @@ // TODO: Move into grammar -use std::collections::HashMap; +use fnv::FnvHashMap; use std::env; use std::io::{self, Write}; use status::*; use variables::Variables; -fn print_list(list: &HashMap<String, String>) { +fn print_list(list: &FnvHashMap<String, String>) { let stdout = io::stdout(); let stdout = &mut stdout.lock(); diff --git a/src/main.rs b/src/main.rs index f745a3db..869a60f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,12 @@ #![feature(box_syntax)] #![feature(plugin)] #![plugin(peg_syntax_ext)] + +// For a performance boost on Linux +// #![feature(alloc_system)] +// extern crate alloc_system; + +extern crate fnv; extern crate glob; extern crate liner; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 00c3ffa2..3b011de4 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -39,7 +39,7 @@ pub mod shell_expand; mod statements; mod quotes; -pub use self::shell_expand::{Index, IndexEnd, ExpanderFunctions, expand_string}; +pub use self::shell_expand::{Index, IndexEnd, ExpanderFunctions, expand_string, expand_tokens, WordToken, WordIterator}; pub use self::arguments::ArgumentSplitter; pub use self::loops::for_grammar::ForExpression; pub use self::statements::{StatementSplitter, StatementError, check_statement}; diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs index 6f1f74de..12407c65 100644 --- a/src/parser/shell_expand/mod.rs +++ b/src/parser/shell_expand/mod.rs @@ -10,7 +10,7 @@ mod words; use self::braces::BraceToken; use self::ranges::parse_range; -use self::words::{WordIterator, WordToken}; +pub use self::words::{WordIterator, WordToken}; pub use self::words::{Index, IndexEnd}; @@ -130,7 +130,7 @@ pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_qu } #[allow(cyclomatic_complexity)] -fn expand_tokens(mut token_buffer: Vec<WordToken>, expand_func: &ExpanderFunctions, +pub fn expand_tokens(mut token_buffer: Vec<WordToken>, expand_func: &ExpanderFunctions, reverse_quoting: bool, contains_brace: bool) -> Vec<String> { let mut output = String::new(); diff --git a/src/shell/assignments.rs b/src/shell/assignments.rs index f9cfb3af..b3313d3c 100644 --- a/src/shell/assignments.rs +++ b/src/shell/assignments.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use fnv::FnvHashMap; use std::io::{self, Write}; use variables::Variables; @@ -7,7 +7,7 @@ use parser::assignments::{self, Binding, Operator, Value}; use parser::{ExpanderFunctions, Index, IndexEnd}; use status::*; -fn print_vars(list: &HashMap<String, String>) { +fn print_vars(list: &FnvHashMap<String, String>) { let stdout = io::stdout(); let stdout = &mut stdout.lock(); @@ -20,7 +20,7 @@ fn print_vars(list: &HashMap<String, String>) { } } -fn print_arrays(list: &HashMap<String, Vec<String>>) { +fn print_arrays(list: &FnvHashMap<String, Vec<String>>) { let stdout = io::stdout(); let stdout = &mut stdout.lock(); diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 45b132cd..0a93de62 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -7,7 +7,7 @@ pub use self::history::ShellHistory; pub use self::job::{Job, JobKind}; pub use self::flow::FlowLogic; -use std::collections::HashMap; +use fnv::FnvHashMap; use std::fs::File; use std::io::{self, Read, Write}; use std::env; @@ -30,25 +30,25 @@ use parser::peg::Pipeline; /// This struct will contain all of the data structures related to this /// instance of the shell. pub struct Shell<'a> { - pub builtins: &'a HashMap<&'static str, Builtin>, + pub builtins: &'a FnvHashMap<&'static str, Builtin>, pub context: Context, pub variables: Variables, flow_control: FlowControl, pub directory_stack: DirectoryStack, - pub functions: HashMap<String, Function>, + pub functions: FnvHashMap<String, Function>, pub previous_status: i32, } impl<'a> Shell<'a> { /// Panics if DirectoryStack construction fails - pub fn new(builtins: &'a HashMap<&'static str, Builtin>) -> Shell<'a> { + pub fn new(builtins: &'a FnvHashMap<&'static str, Builtin>) -> Shell<'a> { Shell { builtins: builtins, context: Context::new(), variables: Variables::default(), flow_control: FlowControl::default(), directory_stack: DirectoryStack::new().expect(""), - functions: HashMap::default(), + functions: FnvHashMap::default(), previous_status: 0, } } @@ -336,7 +336,9 @@ impl<'a> Shell<'a> { // Branch else if -> input == shell function and set the exit_status } else if let Some(function) = self.functions.get(pipeline.jobs[0].command.as_str()).cloned() { if pipeline.jobs[0].args.len() - 1 == function.args.len() { - let mut variables_backup: HashMap<&str, Option<String>> = HashMap::new(); + let mut variables_backup: FnvHashMap<&str, Option<String>> = FnvHashMap::with_capacity_and_hasher ( + 64, Default::default() + ); for (name, value) in function.args.iter().zip(pipeline.jobs[0].args.iter().skip(1)) { variables_backup.insert(name, self.variables.get_var(name)); self.variables.set_var(name, value); diff --git a/src/variables.rs b/src/variables.rs index 4453686e..8a7e0995 100644 --- a/src/variables.rs +++ b/src/variables.rs @@ -1,5 +1,5 @@ // TODO: Move into shell module -use std::collections::HashMap; +use fnv::FnvHashMap; use std::env; use std::path::PathBuf; use std::process; @@ -9,14 +9,14 @@ use liner::Context; use status::{SUCCESS, FAILURE}; pub struct Variables { - pub arrays: HashMap<String, Vec<String>>, - pub variables: HashMap<String, String>, - pub aliases: HashMap<String, String> + pub arrays: FnvHashMap<String, Vec<String>>, + pub variables: FnvHashMap<String, String>, + pub aliases: FnvHashMap<String, String> } impl Default for Variables { fn default() -> Variables { - let mut map = HashMap::new(); + let mut map = FnvHashMap::with_capacity_and_hasher(64, Default::default()); map.insert("DIRECTORY_STACK_SIZE".to_string(), "1000".to_string()); map.insert("HISTORY_SIZE".into(), "1000".into()); map.insert("HISTORY_FILE_ENABLED".into(), "0".into()); @@ -36,7 +36,7 @@ impl Default for Variables { // Initialize the HOME variable env::home_dir().map_or_else(|| env::set_var("HOME", "?"), |path| env::set_var("HOME", path.to_str().unwrap_or("?"))); - Variables { arrays: HashMap::new(), variables: map, aliases: HashMap::new() } + Variables { arrays: FnvHashMap::with_capacity_and_hasher(64, Default::default()), variables: map, aliases: FnvHashMap::with_capacity_and_hasher(64, Default::default()) } } } -- GitLab