Skip to content

Commit a9a8151

Browse files
authored
Rollup merge of rust-lang#67888 - Zoxc:metadata-prefetch, r=matthewjasper
Prefetch some queries used by the metadata encoder This brings the time for `metadata encoding and writing` for `syntex_syntax` from 1.338s to 0.997s with 6 threads in non-incremental debug mode. r? @Mark-Simulacrum
2 parents f4c675c + 027c8d9 commit a9a8151

File tree

3 files changed

+136
-33
lines changed

3 files changed

+136
-33
lines changed

src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ impl<'tcx> TyCtxt<'tcx> {
13231323
}
13241324

13251325
pub fn encode_metadata(self) -> EncodedMetadata {
1326-
let _prof_timer = self.prof.generic_activity("generate_crate_metadata");
1326+
let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata");
13271327
self.cstore.encode_metadata(self)
13281328
}
13291329

src/librustc_metadata/rmeta/encoder.rs

+133-31
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ use rustc_ast::attr;
1818
use rustc_data_structures::fingerprint::Fingerprint;
1919
use rustc_data_structures::fx::FxHashMap;
2020
use rustc_data_structures::stable_hasher::StableHasher;
21-
use rustc_data_structures::sync::Lrc;
21+
use rustc_data_structures::sync::{join, Lrc};
2222
use rustc_hir as hir;
2323
use rustc_hir::def::CtorKind;
24+
use rustc_hir::def_id::DefIdSet;
2425
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2526
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
26-
use rustc_hir::itemlikevisit::ItemLikeVisitor;
27+
use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
2728
use rustc_hir::{AnonConst, GenericParamKind};
2829
use rustc_index::vec::Idx;
2930
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
@@ -467,12 +468,6 @@ impl<'tcx> EncodeContext<'tcx> {
467468
let impls = self.encode_impls();
468469
let impl_bytes = self.position() - i;
469470

470-
// Encode exported symbols info.
471-
i = self.position();
472-
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
473-
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
474-
let exported_symbols_bytes = self.position() - i;
475-
476471
let tcx = self.tcx;
477472

478473
// Encode the items.
@@ -513,6 +508,13 @@ impl<'tcx> EncodeContext<'tcx> {
513508
let proc_macro_data = self.encode_proc_macros();
514509
let proc_macro_data_bytes = self.position() - i;
515510

511+
// Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
512+
// this last to give the prefetching as much time as possible to complete.
513+
i = self.position();
514+
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
515+
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
516+
let exported_symbols_bytes = self.position() - i;
517+
516518
let attrs = tcx.hir().krate_attrs();
517519
let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator);
518520

@@ -888,6 +890,8 @@ impl EncodeContext<'tcx> {
888890
self.encode_generics(def_id);
889891
self.encode_explicit_predicates(def_id);
890892
self.encode_inferred_outlives(def_id);
893+
894+
// This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
891895
self.encode_optimized_mir(def_id);
892896
self.encode_promoted_mir(def_id);
893897
}
@@ -959,6 +963,9 @@ impl EncodeContext<'tcx> {
959963
self.encode_generics(def_id);
960964
self.encode_explicit_predicates(def_id);
961965
self.encode_inferred_outlives(def_id);
966+
967+
// The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
968+
962969
let mir = match ast_item.kind {
963970
hir::ImplItemKind::Const(..) => true,
964971
hir::ImplItemKind::Fn(ref sig, _) => {
@@ -1250,6 +1257,8 @@ impl EncodeContext<'tcx> {
12501257
_ => {}
12511258
}
12521259

1260+
// The following part should be kept in sync with `PrefetchVisitor.visit_item`.
1261+
12531262
let mir = match item.kind {
12541263
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
12551264
hir::ItemKind::Fn(ref sig, ..) => {
@@ -1697,6 +1706,70 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
16971706
}
16981707
}
16991708

1709+
/// Used to prefetch queries which will be needed later by metadata encoding.
1710+
/// Only a subset of the queries are actually prefetched to keep this code smaller.
1711+
struct PrefetchVisitor<'tcx> {
1712+
tcx: TyCtxt<'tcx>,
1713+
mir_keys: &'tcx DefIdSet,
1714+
}
1715+
1716+
impl<'tcx> PrefetchVisitor<'tcx> {
1717+
fn prefetch_mir(&self, def_id: DefId) {
1718+
if self.mir_keys.contains(&def_id) {
1719+
self.tcx.optimized_mir(def_id);
1720+
self.tcx.promoted_mir(def_id);
1721+
}
1722+
}
1723+
}
1724+
1725+
impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
1726+
fn visit_item(&self, item: &hir::Item<'_>) {
1727+
// This should be kept in sync with `encode_info_for_item`.
1728+
let tcx = self.tcx;
1729+
match item.kind {
1730+
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
1731+
self.prefetch_mir(tcx.hir().local_def_id(item.hir_id))
1732+
}
1733+
hir::ItemKind::Fn(ref sig, ..) => {
1734+
let def_id = tcx.hir().local_def_id(item.hir_id);
1735+
let generics = tcx.generics_of(def_id);
1736+
let needs_inline = generics.requires_monomorphization(tcx)
1737+
|| tcx.codegen_fn_attrs(def_id).requests_inline();
1738+
if needs_inline || sig.header.constness == hir::Constness::Const {
1739+
self.prefetch_mir(def_id)
1740+
}
1741+
}
1742+
_ => (),
1743+
}
1744+
}
1745+
1746+
fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) {
1747+
// This should be kept in sync with `encode_info_for_trait_item`.
1748+
self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id));
1749+
}
1750+
1751+
fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
1752+
// This should be kept in sync with `encode_info_for_impl_item`.
1753+
let tcx = self.tcx;
1754+
match impl_item.kind {
1755+
hir::ImplItemKind::Const(..) => {
1756+
self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id))
1757+
}
1758+
hir::ImplItemKind::Fn(ref sig, _) => {
1759+
let def_id = tcx.hir().local_def_id(impl_item.hir_id);
1760+
let generics = tcx.generics_of(def_id);
1761+
let needs_inline = generics.requires_monomorphization(tcx)
1762+
|| tcx.codegen_fn_attrs(def_id).requests_inline();
1763+
let is_const_fn = sig.header.constness == hir::Constness::Const;
1764+
if needs_inline || is_const_fn {
1765+
self.prefetch_mir(def_id)
1766+
}
1767+
}
1768+
hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => (),
1769+
}
1770+
}
1771+
}
1772+
17001773
// NOTE(eddyb) The following comment was preserved for posterity, even
17011774
// though it's no longer relevant as EBML (which uses nested & tagged
17021775
// "documents") was replaced with a scheme that can't go out of bounds.
@@ -1721,35 +1794,64 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
17211794
// generated regardless of trailing bytes that end up in it.
17221795

17231796
pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
1797+
// Since encoding metadata is not in a query, and nothing is cached,
1798+
// there's no need to do dep-graph tracking for any of it.
1799+
tcx.dep_graph.assert_ignored();
1800+
1801+
join(
1802+
|| encode_metadata_impl(tcx),
1803+
|| {
1804+
if tcx.sess.threads() == 1 {
1805+
return;
1806+
}
1807+
// Prefetch some queries used by metadata encoding.
1808+
// This is not necessary for correctness, but is only done for performance reasons.
1809+
// It can be removed if it turns out to cause trouble or be detrimental to performance.
1810+
join(
1811+
|| {
1812+
if !tcx.sess.opts.output_types.should_codegen() {
1813+
// We won't emit MIR, so don't prefetch it.
1814+
return;
1815+
}
1816+
tcx.hir().krate().par_visit_all_item_likes(&PrefetchVisitor {
1817+
tcx,
1818+
mir_keys: tcx.mir_keys(LOCAL_CRATE),
1819+
});
1820+
},
1821+
|| tcx.exported_symbols(LOCAL_CRATE),
1822+
);
1823+
},
1824+
)
1825+
.0
1826+
}
1827+
1828+
fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
17241829
let mut encoder = opaque::Encoder::new(vec![]);
17251830
encoder.emit_raw_bytes(METADATA_HEADER);
17261831

17271832
// Will be filled with the root position after encoding everything.
17281833
encoder.emit_raw_bytes(&[0, 0, 0, 0]);
17291834

1730-
// Since encoding metadata is not in a query, and nothing is cached,
1731-
// there's no need to do dep-graph tracking for any of it.
1732-
let (root, mut result) = tcx.dep_graph.with_ignore(move || {
1733-
let mut ecx = EncodeContext {
1734-
opaque: encoder,
1735-
tcx,
1736-
per_def: Default::default(),
1737-
lazy_state: LazyState::NoNode,
1738-
type_shorthands: Default::default(),
1739-
predicate_shorthands: Default::default(),
1740-
source_file_cache: tcx.sess.source_map().files()[0].clone(),
1741-
interpret_allocs: Default::default(),
1742-
interpret_allocs_inverse: Default::default(),
1743-
};
1744-
1745-
// Encode the rustc version string in a predictable location.
1746-
rustc_version().encode(&mut ecx).unwrap();
1747-
1748-
// Encode all the entries and extra information in the crate,
1749-
// culminating in the `CrateRoot` which points to all of it.
1750-
let root = ecx.encode_crate_root();
1751-
(root, ecx.opaque.into_inner())
1752-
});
1835+
let mut ecx = EncodeContext {
1836+
opaque: encoder,
1837+
tcx,
1838+
per_def: Default::default(),
1839+
lazy_state: LazyState::NoNode,
1840+
type_shorthands: Default::default(),
1841+
predicate_shorthands: Default::default(),
1842+
source_file_cache: tcx.sess.source_map().files()[0].clone(),
1843+
interpret_allocs: Default::default(),
1844+
interpret_allocs_inverse: Default::default(),
1845+
};
1846+
1847+
// Encode the rustc version string in a predictable location.
1848+
rustc_version().encode(&mut ecx).unwrap();
1849+
1850+
// Encode all the entries and extra information in the crate,
1851+
// culminating in the `CrateRoot` which points to all of it.
1852+
let root = ecx.encode_crate_root();
1853+
1854+
let mut result = ecx.opaque.into_inner();
17531855

17541856
// Encode the root position.
17551857
let header = METADATA_HEADER.len();

src/librustc_metadata/rmeta/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,15 @@ crate struct CrateRoot<'tcx> {
196196
source_map: Lazy<[rustc_span::SourceFile]>,
197197
def_path_table: Lazy<map::definitions::DefPathTable>,
198198
impls: Lazy<[TraitImpls]>,
199-
exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
200199
interpret_alloc_index: Lazy<[u32]>,
201200

202201
per_def: LazyPerDefTables<'tcx>,
203202

204203
/// The DefIndex's of any proc macros declared by this crate.
205204
proc_macro_data: Option<Lazy<[DefIndex]>>,
206205

206+
exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
207+
207208
compiler_builtins: bool,
208209
needs_allocator: bool,
209210
needs_panic_runtime: bool,

0 commit comments

Comments
 (0)