Skip to content

Commit 7b5a9e9

Browse files
committed
Auto merge of #78448 - rylev:cache-foreign_modules, r=wesleywiser
foreign_modules query hash table lookups When compiling a large monolithic crate we're seeing huge times in the `foreign_modules` query due to repeated iteration over foreign modules (in order to find a module by its id). This implements hash table lookups so that which massively reduces time spent in that query in this particular case. We'll need to see if the overhead of creating the hash table has a negative impact on performance in more normal compilation scenarios. I'm working with `@wesleywiser` on this.
2 parents 4c0c5e0 + 81444b2 commit 7b5a9e9

File tree

7 files changed

+17
-14
lines changed

7 files changed

+17
-14
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ pub fn provide_both(providers: &mut Providers) {
378378
.collect::<FxHashMap<_, _>>();
379379

380380
let mut ret = FxHashMap::default();
381-
for lib in tcx.foreign_modules(cnum).iter() {
382-
let module = def_id_to_native_lib.get(&lib.def_id).and_then(|s| s.wasm_import_module);
381+
for (def_id, lib) in tcx.foreign_modules(cnum).iter() {
382+
let module = def_id_to_native_lib.get(&def_id).and_then(|s| s.wasm_import_module);
383383
let module = match module {
384384
Some(s) => s,
385385
None => continue,

compiler/rustc_codegen_ssa/src/base.rs

-2
Original file line numberDiff line numberDiff line change
@@ -860,8 +860,6 @@ pub fn provide_both(providers: &mut Providers) {
860860

861861
providers.dllimport_foreign_items = |tcx, krate| {
862862
let module_map = tcx.foreign_modules(krate);
863-
let module_map =
864-
module_map.iter().map(|lib| (lib.def_id, lib)).collect::<FxHashMap<_, _>>();
865863

866864
let dllimports = tcx
867865
.native_libraries(krate)

compiler/rustc_metadata/src/rmeta/decoder.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1414,12 +1414,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14141414
}
14151415
}
14161416

1417-
fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
1417+
fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> Lrc<FxHashMap<DefId, ForeignModule>> {
14181418
if self.root.is_proc_macro_crate() {
14191419
// Proc macro crates do not have any *target* foreign modules.
1420-
&[]
1420+
Lrc::new(FxHashMap::default())
14211421
} else {
1422-
tcx.arena.alloc_from_iter(self.root.foreign_modules.decode((self, tcx.sess)))
1422+
let modules: FxHashMap<DefId, ForeignModule> =
1423+
self.root.foreign_modules.decode((self, tcx.sess)).map(|m| (m.def_id, m)).collect();
1424+
Lrc::new(modules)
14231425
}
14241426
}
14251427

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ use crate::rmeta::{self, encoder};
66

77
use rustc_ast as ast;
88
use rustc_ast::expand::allocator::AllocatorKind;
9+
use rustc_data_structures::stable_map::FxHashMap;
910
use rustc_data_structures::svh::Svh;
1011
use rustc_hir as hir;
1112
use rustc_hir::def::DefKind;
1213
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
1314
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1415
use rustc_middle::hir::exports::Export;
16+
use rustc_middle::middle::cstore::ForeignModule;
1517
use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
1618
use rustc_middle::middle::exported_symbols::ExportedSymbol;
1719
use rustc_middle::middle::stability::DeprecationEntry;
@@ -266,9 +268,8 @@ pub fn provide(providers: &mut Providers) {
266268
Some(id) => id,
267269
None => return false,
268270
};
269-
tcx.foreign_modules(id.krate)
270-
.iter()
271-
.find(|m| m.def_id == fm_id)
271+
let map = tcx.foreign_modules(id.krate);
272+
map.get(&fm_id)
272273
.expect("failed to find foreign module")
273274
.foreign_items
274275
.contains(&id)
@@ -281,7 +282,9 @@ pub fn provide(providers: &mut Providers) {
281282
},
282283
foreign_modules: |tcx, cnum| {
283284
assert_eq!(cnum, LOCAL_CRATE);
284-
&tcx.arena.alloc(foreign_modules::collect(tcx))[..]
285+
let modules: FxHashMap<DefId, ForeignModule> =
286+
foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect();
287+
Lrc::new(modules)
285288
},
286289
link_args: |tcx, cnum| {
287290
assert_eq!(cnum, LOCAL_CRATE);

compiler/rustc_metadata/src/rmeta/encoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,7 @@ impl EncodeContext<'a, 'tcx> {
15021502
fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
15031503
empty_proc_macro!(self);
15041504
let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1505-
self.lazy(foreign_modules.iter().cloned())
1505+
self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned())
15061506
}
15071507

15081508
fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable) {

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1168,7 +1168,7 @@ rustc_queries! {
11681168
}
11691169

11701170
Other {
1171-
query foreign_modules(_: CrateNum) -> &'tcx [ForeignModule] {
1171+
query foreign_modules(_: CrateNum) -> Lrc<FxHashMap<DefId, ForeignModule>> {
11721172
desc { "looking up the foreign modules of a linked crate" }
11731173
}
11741174

compiler/rustc_passes/src/diagnostic_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
102102
tcx.hir().krate().visit_all_item_likes(&mut collector);
103103
// FIXME(visit_all_item_likes): Foreign items are not visited
104104
// here, so we have to manually look at them for now.
105-
for foreign_module in tcx.foreign_modules(LOCAL_CRATE) {
105+
for (_, foreign_module) in tcx.foreign_modules(LOCAL_CRATE).iter() {
106106
for &foreign_item in foreign_module.foreign_items.iter() {
107107
match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
108108
hir::Node::ForeignItem(item) => {

0 commit comments

Comments
 (0)