about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-04 21:17:19 +0000
committerbors <bors@rust-lang.org>2024-07-04 21:17:19 +0000
commitcc8da78a036dc3c15c35a97651b02af9a6d30c1e (patch)
tree7fed19378e80e1b3d189f66557a85c15cb8cf971
parentc4225812973cee4bba952cbf7a421f69871fed0d (diff)
parent529a3f4ce609f4bc98215185838351d9815fbdc1 (diff)
Auto merge of #127288 - lqd:typelen-cache, r=compiler-errors
cache type sizes in type-size limit visitor

This is basically https://github.com/rust-lang/rust/pull/125507#issuecomment-2206813779 as lcnr can't open the PR now.

Locally it reduces the `itertools` regression by quite a bit, to "only +50%" compared to nightly (that includes overhead from the local lack of artifact post-processing, and is just a data point to compare to the 10-20x timings without the cache).

```console
Benchmark 1: cargo +stage1 build --release
  Time (mean ± σ):      2.721 s ±  0.009 s    [User: 2.446 s, System: 0.325 s]
  Range (min … max):    2.710 s …  2.738 s    10 runs

Benchmark 2: cargo +nightly build --release
  Time (mean ± σ):      1.784 s ±  0.005 s    [User: 1.540 s, System: 0.279 s]
  Range (min … max):    1.778 s …  1.792 s    10 runs

Summary
  cargo +nightly build --release ran
    1.52 ± 0.01 times faster than cargo +stage1 build --release
```

On master, it's from 34s to the 2.7s above.

r? compiler-errors
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs19
1 files changed, 16 insertions, 3 deletions
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index ae54411d788..c50a98e88fd 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -5,6 +5,7 @@ use crate::ty::{
     self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
     TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::Namespace;
@@ -388,13 +389,25 @@ impl<'tcx> InstanceKind<'tcx> {
 }
 
 fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
-    struct Visitor {
+    struct Visitor<'tcx> {
         type_length: usize,
+        cache: FxHashMap<Ty<'tcx>, usize>,
     }
-    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor {
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
         fn visit_ty(&mut self, t: Ty<'tcx>) {
+            if let Some(&value) = self.cache.get(&t) {
+                self.type_length += value;
+                return;
+            }
+
+            let prev = self.type_length;
             self.type_length += 1;
             t.super_visit_with(self);
+
+            // We don't try to use the cache if the type is fairly small.
+            if self.type_length > 16 {
+                self.cache.insert(t, self.type_length - prev);
+            }
         }
 
         fn visit_const(&mut self, ct: ty::Const<'tcx>) {
@@ -402,7 +415,7 @@ fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
             ct.super_visit_with(self);
         }
     }
-    let mut visitor = Visitor { type_length: 0 };
+    let mut visitor = Visitor { type_length: 0, cache: Default::default() };
     item.visit_with(&mut visitor);
 
     visitor.type_length