Skip to content

Commit

Permalink
auto merge of #12635 : alexcrichton/rust/speedy-hash, r=brson
Browse files Browse the repository at this point in the history
This leverages the new hashing framework and hashmap implementation to provide a
much speedier hashing algorithm for node ids and def ids. The hash algorithm
used is currentl FNV hashing, but it's quite easy to swap out.

I originally implemented hashing as the identity function, but this actually
ended up in slowing down rustc compiling libstd from 8s to 13s. I would suspect
that this is a result of a large number of collisions.

With FNV hashing, we get these timings (compiling with --no-trans, in seconds):

|           |  before  |  after  |
|-----------|---------:|--------:|
| libstd    |   8.324  |  6.703  |
| stdtest   |  47.674  | 46.857  |
| libsyntax |   9.918  |  8.400  |
  • Loading branch information
bors committed Mar 7, 2014
2 parents 0e95b08 + 0a84132 commit 5862c0c
Show file tree
Hide file tree
Showing 31 changed files with 412 additions and 212 deletions.
11 changes: 8 additions & 3 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
use middle;
use util::common::time;
use util::ppaux;
use util::nodemap::NodeSet;

use serialize::{json, Encodable};

Expand All @@ -38,7 +39,7 @@ use std::os;
use std::vec;
use std::vec_ng::Vec;
use std::vec_ng;
use collections::{HashMap, HashSet};
use collections::HashMap;
use getopts::{optopt, optmulti, optflag, optflagopt, opt};
use MaybeHasArg = getopts::Maybe;
use OccurOptional = getopts::Optional;
Expand Down Expand Up @@ -223,8 +224,12 @@ pub fn phase_2_configure_and_expand(sess: Session,
front::config::strip_unconfigured_items(krate));

krate = time(time_passes, "expansion", krate, |krate| {
let cfg = syntax::ext::expand::ExpansionConfig {
loader: loader,
deriving_hash_type_parameter: sess.features.default_type_params.get()
};
syntax::ext::expand::expand_crate(sess.parse_sess,
loader,
cfg,
krate)
});
// dump the syntax-time crates
Expand Down Expand Up @@ -258,7 +263,7 @@ pub struct CrateAnalysis {
public_items: middle::privacy::PublicItems,
ty_cx: ty::ctxt,
maps: astencode::Maps,
reachable: @RefCell<HashSet<ast::NodeId>>
reachable: @RefCell<NodeSet>,
}

/// Run the resolution, typechecking, region checking and other
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use syntax::attr;
use syntax::codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
use syntax::codemap;
use syntax::ext::base::ExtCtxt;
use syntax::ext::expand::ExpansionConfig;
use syntax::fold::Folder;
use syntax::fold;
use syntax::opt_vec;
Expand Down Expand Up @@ -165,7 +166,11 @@ fn generate_test_harness(sess: session::Session, krate: ast::Crate)
let loader = &mut Loader::new(sess);
let mut cx: TestCtxt = TestCtxt {
sess: sess,
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(),
ExpansionConfig {
loader: loader,
deriving_hash_type_parameter: false,
}),
path: RefCell::new(~[]),
testfns: RefCell::new(~[]),
is_test_crate: is_test_crate(&krate),
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This API is completely unstable and subject to change.

#[allow(deprecated)];
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
#[feature(quote)];
#[feature(quote, default_type_params)];

extern crate extra;
extern crate flate;
Expand Down Expand Up @@ -125,6 +125,7 @@ pub mod util {
pub mod common;
pub mod ppaux;
pub mod sha2;
pub mod nodemap;
}

pub mod lib {
Expand Down
11 changes: 6 additions & 5 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use middle::astencode;
use middle::ty;
use middle::typeck;
use middle;
use util::nodemap::{NodeMap, NodeSet};

use serialize::Encodable;
use std::cast;
Expand All @@ -31,7 +32,7 @@ use std::hash;
use std::hash::Hash;
use std::io::MemWriter;
use std::str;
use collections::{HashMap, HashSet};
use collections::HashMap;
use syntax::abi::AbiSet;
use syntax::ast::*;
use syntax::ast;
Expand Down Expand Up @@ -69,8 +70,8 @@ pub struct EncodeParams<'a> {
diag: @SpanHandler,
tcx: ty::ctxt,
reexports2: middle::resolve::ExportMap2,
item_symbols: &'a RefCell<HashMap<ast::NodeId, ~str>>,
non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
item_symbols: &'a RefCell<NodeMap<~str>>,
non_inlineable_statics: &'a RefCell<NodeSet>,
link_meta: &'a LinkMeta,
cstore: @cstore::CStore,
encode_inlined_item: EncodeInlinedItem<'a>,
Expand All @@ -97,8 +98,8 @@ pub struct EncodeContext<'a> {
tcx: ty::ctxt,
stats: @Stats,
reexports2: middle::resolve::ExportMap2,
item_symbols: &'a RefCell<HashMap<ast::NodeId, ~str>>,
non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
item_symbols: &'a RefCell<NodeMap<~str>>,
non_inlineable_statics: &'a RefCell<NodeSet>,
link_meta: &'a LinkMeta,
cstore: &'a cstore::CStore,
encode_inlined_item: EncodeInlinedItem<'a>,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ use middle::cfg::*;
use middle::graph;
use middle::typeck;
use middle::ty;
use collections::HashMap;
use syntax::ast;
use syntax::ast_util;
use syntax::opt_vec;
use util::nodemap::NodeMap;

struct CFGBuilder {
tcx: ty::ctxt,
method_map: typeck::MethodMap,
exit_map: HashMap<ast::NodeId, CFGIndex>,
exit_map: NodeMap<CFGIndex>,
graph: CFGGraph,
loop_scopes: ~[LoopScope],
}
Expand All @@ -35,7 +35,7 @@ pub fn construct(tcx: ty::ctxt,
method_map: typeck::MethodMap,
blk: &ast::Block) -> CFG {
let mut cfg_builder = CFGBuilder {
exit_map: HashMap::new(),
exit_map: NodeMap::new(),
graph: graph::Graph::new(),
tcx: tcx,
method_map: method_map,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ Uses `Graph` as the underlying representation.
use middle::graph;
use middle::ty;
use middle::typeck;
use collections::HashMap;
use syntax::ast;
use syntax::opt_vec::OptVec;
use util::nodemap::NodeMap;

mod construct;

pub struct CFG {
exit_map: HashMap<ast::NodeId, CFGIndex>,
exit_map: NodeMap<CFGIndex>,
graph: CFGGraph,
entry: CFGIndex,
exit: CFGIndex,
Expand Down
17 changes: 9 additions & 8 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use middle::astencode;
use middle::ty;
use middle::typeck::astconv;
use middle;
use util::nodemap::{DefIdMap, NodeMap};

use syntax::ast::*;
use syntax::parse::token::InternedString;
Expand Down Expand Up @@ -66,7 +67,7 @@ pub enum constness {
non_const
}

type constness_cache = HashMap<ast::DefId, constness>;
type constness_cache = DefIdMap<constness>;

pub fn join(a: constness, b: constness) -> constness {
match (a, b) {
Expand Down Expand Up @@ -134,9 +135,9 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
}
let maps = astencode::Maps {
root_map: @RefCell::new(HashMap::new()),
method_map: @RefCell::new(HashMap::new()),
vtable_map: @RefCell::new(HashMap::new()),
capture_map: @RefCell::new(HashMap::new())
method_map: @RefCell::new(NodeMap::new()),
vtable_map: @RefCell::new(NodeMap::new()),
capture_map: @RefCell::new(NodeMap::new())
};
let e = match csearch::maybe_get_item_ast(tcx, enum_def,
|a, b, c, d| astencode::decode_inlined_item(a, b,
Expand Down Expand Up @@ -184,9 +185,9 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
}
let maps = astencode::Maps {
root_map: @RefCell::new(HashMap::new()),
method_map: @RefCell::new(HashMap::new()),
vtable_map: @RefCell::new(HashMap::new()),
capture_map: @RefCell::new(HashMap::new())
method_map: @RefCell::new(NodeMap::new()),
vtable_map: @RefCell::new(NodeMap::new()),
capture_map: @RefCell::new(NodeMap::new())
};
let e = match csearch::maybe_get_item_ast(tcx, def_id,
|a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) {
Expand Down Expand Up @@ -305,7 +306,7 @@ pub fn process_crate(krate: &ast::Crate,
tcx: ty::ctxt) {
let mut v = ConstEvalVisitor {
tcx: tcx,
ccache: HashMap::new(),
ccache: DefIdMap::new(),
};
visit::walk_crate(&mut v, krate, ());
tcx.sess.abort_if_errors();
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
use std::io;
use std::uint;
use std::vec;
use collections::HashMap;
use syntax::ast;
use syntax::ast_util;
use syntax::ast_util::IdRange;
use syntax::print::{pp, pprust};
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;
use util::nodemap::NodeMap;

#[deriving(Clone)]
pub struct DataFlowContext<O> {
Expand All @@ -45,7 +45,7 @@ pub struct DataFlowContext<O> {
priv words_per_id: uint,

// mapping from node to bitset index.
priv nodeid_to_bitset: HashMap<ast::NodeId,uint>,
priv nodeid_to_bitset: NodeMap<uint>,

// Bit sets per id. The following three fields (`gens`, `kills`,
// and `on_entry`) all have the same structure. For each id in
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
tcx: tcx,
method_map: method_map,
words_per_id: words_per_id,
nodeid_to_bitset: HashMap::new(),
nodeid_to_bitset: NodeMap::new(),
bits_per_id: bits_per_id,
oper: oper,
gens: gens,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use middle::lint::{allow, contains_lint, DeadCode};
use middle::privacy;
use middle::ty;
use middle::typeck;
use util::nodemap::NodeSet;

use collections::HashSet;
use syntax::ast;
Expand Down Expand Up @@ -252,7 +253,7 @@ impl Visitor<()> for LifeSeeder {

fn create_and_seed_worklist(tcx: ty::ctxt,
exported_items: &privacy::ExportedItems,
reachable_symbols: &HashSet<ast::NodeId>,
reachable_symbols: &NodeSet,
krate: &ast::Crate) -> ~[ast::NodeId] {
let mut worklist = ~[];

Expand Down Expand Up @@ -286,7 +287,7 @@ fn create_and_seed_worklist(tcx: ty::ctxt,
fn find_live(tcx: ty::ctxt,
method_map: typeck::MethodMap,
exported_items: &privacy::ExportedItems,
reachable_symbols: &HashSet<ast::NodeId>,
reachable_symbols: &NodeSet,
krate: &ast::Crate)
-> ~HashSet<ast::NodeId> {
let worklist = create_and_seed_worklist(tcx, exported_items,
Expand Down Expand Up @@ -409,7 +410,7 @@ impl Visitor<()> for DeadVisitor {
pub fn check_crate(tcx: ty::ctxt,
method_map: typeck::MethodMap,
exported_items: &privacy::ExportedItems,
reachable_symbols: &HashSet<ast::NodeId>,
reachable_symbols: &NodeSet,
krate: &ast::Crate) {
let live_symbols = find_live(tcx, method_map, exported_items,
reachable_symbols, krate);
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/middle/freevars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

use middle::resolve;
use middle::ty;
use util::nodemap::{NodeMap, NodeSet};

use collections::HashMap;
use syntax::codemap::Span;
use syntax::{ast, ast_util};
use syntax::visit;
Expand All @@ -30,10 +30,10 @@ pub struct freevar_entry {
span: Span //< First span where it is accessed (there can be multiple)
}
pub type freevar_info = @~[@freevar_entry];
pub type freevar_map = HashMap<ast::NodeId, freevar_info>;
pub type freevar_map = NodeMap<freevar_info>;

struct CollectFreevarsVisitor {
seen: HashMap<ast::NodeId, ()>,
seen: NodeSet,
refs: ~[@freevar_entry],
def_map: resolve::DefMap,
}
Expand Down Expand Up @@ -65,12 +65,12 @@ impl Visitor<int> for CollectFreevarsVisitor {
}
if i == depth { // Made it to end of loop
let dnum = ast_util::def_id_of_def(def).node;
if !self.seen.contains_key(&dnum) {
if !self.seen.contains(&dnum) {
self.refs.push(@freevar_entry {
def: def,
span: expr.span,
});
self.seen.insert(dnum, ());
self.seen.insert(dnum);
}
}
}
Expand All @@ -89,7 +89,7 @@ impl Visitor<int> for CollectFreevarsVisitor {
// of the AST, we take a walker function that we invoke with a visitor
// in order to start the search.
fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) -> freevar_info {
let seen = HashMap::new();
let seen = NodeSet::new();
let refs = ~[];

let mut v = CollectFreevarsVisitor {
Expand Down Expand Up @@ -129,7 +129,7 @@ pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
freevar_map {
let mut visitor = AnnotateFreevarsVisitor {
def_map: def_map,
freevars: HashMap::new(),
freevars: NodeMap::new(),
};
visit::walk_crate(&mut visitor, krate, ());

Expand Down
20 changes: 10 additions & 10 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ use middle::pat_util;
use middle::ty;
use middle::typeck;
use middle::moves;
use util::nodemap::NodeMap;

use std::cast::transmute;
use std::cell::{Cell, RefCell};
Expand All @@ -116,7 +117,6 @@ use std::io;
use std::str;
use std::uint;
use std::vec;
use collections::HashMap;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::parse::token::special_idents;
Expand Down Expand Up @@ -258,9 +258,9 @@ pub struct IrMaps {

num_live_nodes: Cell<uint>,
num_vars: Cell<uint>,
live_node_map: RefCell<HashMap<NodeId, LiveNode>>,
variable_map: RefCell<HashMap<NodeId, Variable>>,
capture_info_map: RefCell<HashMap<NodeId, @~[CaptureInfo]>>,
live_node_map: RefCell<NodeMap<LiveNode>>,
variable_map: RefCell<NodeMap<Variable>>,
capture_info_map: RefCell<NodeMap<@~[CaptureInfo]>>,
var_kinds: RefCell<~[VarKind]>,
lnks: RefCell<~[LiveNodeKind]>,
}
Expand All @@ -275,9 +275,9 @@ fn IrMaps(tcx: ty::ctxt,
capture_map: capture_map,
num_live_nodes: Cell::new(0),
num_vars: Cell::new(0),
live_node_map: RefCell::new(HashMap::new()),
variable_map: RefCell::new(HashMap::new()),
capture_info_map: RefCell::new(HashMap::new()),
live_node_map: RefCell::new(NodeMap::new()),
variable_map: RefCell::new(NodeMap::new()),
capture_info_map: RefCell::new(NodeMap::new()),
var_kinds: RefCell::new(~[]),
lnks: RefCell::new(~[]),
}
Expand Down Expand Up @@ -584,7 +584,7 @@ static ACC_READ: uint = 1u;
static ACC_WRITE: uint = 2u;
static ACC_USE: uint = 4u;

pub type LiveNodeMap = @RefCell<HashMap<NodeId, LiveNode>>;
pub type LiveNodeMap = @RefCell<NodeMap<LiveNode>>;

pub struct Liveness {
tcx: ty::ctxt,
Expand Down Expand Up @@ -613,8 +613,8 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness {
ir.num_vars.get(),
invalid_users())),
loop_scope: @RefCell::new(~[]),
break_ln: @RefCell::new(HashMap::new()),
cont_ln: @RefCell::new(HashMap::new()),
break_ln: @RefCell::new(NodeMap::new()),
cont_ln: @RefCell::new(NodeMap::new()),
}
}

Expand Down
Loading

0 comments on commit 5862c0c

Please sign in to comment.