about summary refs log tree commit diff
path: root/compiler/rustc_mir
diff options
context:
space:
mode:
authorAman Arora <me@aman-arora.com>2021-05-05 15:57:08 -0400
committerAman Arora <me@aman-arora.com>2021-06-28 14:21:55 -0400
commitfc273e9bf2ab4594e8dcdb737b63bffb3f6b08c9 (patch)
tree5d4c81800d048385b8b3d24b8f70bad4ad03bdae /compiler/rustc_mir
parent3e9d7ecf784e5ecaf7437d04be3992ad23fa7cb6 (diff)
downloadrust-fc273e9bf2ab4594e8dcdb737b63bffb3f6b08c9.tar.gz
rust-fc273e9bf2ab4594e8dcdb737b63bffb3f6b08c9.zip
Introduce -Zprofile-closures to evaluate the impact of 2229
This creates a CSV with name "closure_profile_XXXXX.csv", where the
variable part is the process id of the compiler.

To profile a cargo project you can run one of the following depending on
if you're compiling a library or a binary:

```
cargo +stage1 rustc --lib -- -Zprofile-closures
cargo +stage1 rustc --bin -- -Zprofile-closures
```
Diffstat (limited to 'compiler/rustc_mir')
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs7
-rw-r--r--compiler/rustc_mir/src/monomorphize/mod.rs1
-rw-r--r--compiler/rustc_mir/src/monomorphize/util.rs73
3 files changed, 81 insertions, 0 deletions
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 0ab9aa8e1bf..4bd431dcc6a 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -1071,6 +1071,13 @@ fn create_fn_mono_item<'tcx>(
     source: Span,
 ) -> Spanned<MonoItem<'tcx>> {
     debug!("create_fn_mono_item(instance={})", instance);
+
+    let def_id = instance.def_id();
+    if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id)
+    {
+        monomorphize::util::dump_closure_profile(tcx, instance);
+    }
+
     respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
 }
 
diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs
index 9ca4b6687f1..57d2723cf9c 100644
--- a/compiler/rustc_mir/src/monomorphize/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/mod.rs
@@ -7,6 +7,7 @@ use rustc_hir::lang_items::LangItem;
 pub mod collector;
 pub mod partitioning;
 pub mod polymorphize;
+pub mod util;
 
 fn custom_coerce_unsize_info<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_mir/src/monomorphize/util.rs
new file mode 100644
index 00000000000..799b4e18c24
--- /dev/null
+++ b/compiler/rustc_mir/src/monomorphize/util.rs
@@ -0,0 +1,73 @@
+use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt};
+use std::fs::OpenOptions;
+use std::io::prelude::*;
+
+/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on
+/// closure size into a CSV.
+///
+/// During the same compile all closures dump the information in the same file
+/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked.
+crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) {
+    let mut file = if let Ok(file) = OpenOptions::new()
+        .create(true)
+        .append(true)
+        .open(&format!("closure_profile_{}.csv", std::process::id()))
+    {
+        file
+    } else {
+        eprintln!("Cound't open file for writing closure profile");
+        return;
+    };
+
+    let closure_def_id = closure_instance.def_id();
+    let typeck_results = tcx.typeck(closure_def_id.expect_local());
+
+    if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
+        let param_env = ty::ParamEnv::reveal_all();
+
+        let ClosureSizeProfileData { before_feature_tys, after_feature_tys } =
+            typeck_results.closure_size_eval[&closure_def_id];
+
+        let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
+            closure_instance.substs,
+            param_env,
+            before_feature_tys,
+        );
+        let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
+            closure_instance.substs,
+            param_env,
+            after_feature_tys,
+        );
+
+        let new_size = tcx
+            .layout_of(param_env.and(after_feature_tys))
+            .map(|l| format!("{:?}", l.size.bytes()))
+            .unwrap_or_else(|e| format!("Failed {:?}", e));
+
+        let old_size = tcx
+            .layout_of(param_env.and(before_feature_tys))
+            .map(|l| format!("{:?}", l.size.bytes()))
+            .unwrap_or_else(|e| format!("Failed {:?}", e));
+
+        let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+        let closure_span = tcx.hir().span(closure_hir_id);
+        let src_file = tcx.sess.source_map().span_to_filename(closure_span);
+        let line_nos = tcx
+            .sess
+            .source_map()
+            .span_to_lines(closure_span)
+            .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
+            .unwrap_or_else(|e| format!("{:?}", e));
+
+        if let Err(e) = writeln!(
+            file,
+            "{}, {}, {}, {:?}",
+            old_size,
+            new_size,
+            src_file.prefer_local(),
+            line_nos
+        ) {
+            eprintln!("Error writting to file {}", e.to_string())
+        }
+    }
+}