diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-06 14:43:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-06 14:43:37 +0100 |
commit | 7d39b13996e312a8a738ed0dfccab45978fc42f8 (patch) | |
tree | 91761b9bf78d9015fbb6083b9245eb9f6133e234 | |
parent | 12e86433ab57ee8b1c96b8da0480fd311752487b (diff) | |
parent | 4e2a6ac7eae3ff193962421cc3c86e5d8f9a7e31 (diff) |
Merge #8364
8364: Memory usage improvements r=jonas-schievink a=alexmaco
These are mostly focused on splitting up enum variants with large size differences between variants by `Box`-ing things up.
In my testing this reduces the memory usage somewhere in the low percentages, even though the measurements are quite noisy.
Co-authored-by: Alexandru Macovei <[email protected]>
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 14 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/vfs/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/vfs/src/path_interner.rs | 29 |
8 files changed, 54 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock index e40c12a92..ca0311595 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1867,6 +1867,7 @@ name = "vfs" | |||
1867 | version = "0.0.0" | 1867 | version = "0.0.0" |
1868 | dependencies = [ | 1868 | dependencies = [ |
1869 | "fst", | 1869 | "fst", |
1870 | "indexmap", | ||
1870 | "paths", | 1871 | "paths", |
1871 | "rustc-hash", | 1872 | "rustc-hash", |
1872 | ] | 1873 | ] |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 63e89a1f4..1e743e5d5 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -322,8 +322,10 @@ impl ExprCollector<'_> { | |||
322 | Vec::new() | 322 | Vec::new() |
323 | }; | 323 | }; |
324 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 324 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
325 | let generic_args = | 325 | let generic_args = e |
326 | e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); | 326 | .generic_arg_list() |
327 | .and_then(|it| GenericArgs::from_ast(&self.ctx(), it)) | ||
328 | .map(Box::new); | ||
327 | self.alloc_expr( | 329 | self.alloc_expr( |
328 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 330 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
329 | syntax_ptr, | 331 | syntax_ptr, |
@@ -385,7 +387,7 @@ impl ExprCollector<'_> { | |||
385 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) | 387 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) |
386 | } | 388 | } |
387 | ast::Expr::RecordExpr(e) => { | 389 | ast::Expr::RecordExpr(e) => { |
388 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 390 | let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
389 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { | 391 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
390 | let fields = nfl | 392 | let fields = nfl |
391 | .fields() | 393 | .fields() |
@@ -430,7 +432,7 @@ impl ExprCollector<'_> { | |||
430 | } | 432 | } |
431 | ast::Expr::CastExpr(e) => { | 433 | ast::Expr::CastExpr(e) => { |
432 | let expr = self.collect_expr_opt(e.expr()); | 434 | let expr = self.collect_expr_opt(e.expr()); |
433 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); | 435 | let type_ref = Box::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); |
434 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 436 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
435 | } | 437 | } |
436 | ast::Expr::RefExpr(e) => { | 438 | ast::Expr::RefExpr(e) => { |
@@ -469,8 +471,10 @@ impl ExprCollector<'_> { | |||
469 | arg_types.push(type_ref); | 471 | arg_types.push(type_ref); |
470 | } | 472 | } |
471 | } | 473 | } |
472 | let ret_type = | 474 | let ret_type = e |
473 | e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); | 475 | .ret_type() |
476 | .and_then(|r| r.ty()) | ||
477 | .map(|it| Box::new(TypeRef::from_ast(&self.ctx(), it))); | ||
474 | let body = self.collect_expr_opt(e.body()); | 478 | let body = self.collect_expr_opt(e.body()); |
475 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 479 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
476 | } | 480 | } |
@@ -755,7 +759,7 @@ impl ExprCollector<'_> { | |||
755 | } | 759 | } |
756 | } | 760 | } |
757 | ast::Pat::TupleStructPat(p) => { | 761 | ast::Pat::TupleStructPat(p) => { |
758 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 762 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
759 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); | 763 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); |
760 | Pat::TupleStruct { path, args, ellipsis } | 764 | Pat::TupleStruct { path, args, ellipsis } |
761 | } | 765 | } |
@@ -765,7 +769,7 @@ impl ExprCollector<'_> { | |||
765 | Pat::Ref { pat, mutability } | 769 | Pat::Ref { pat, mutability } |
766 | } | 770 | } |
767 | ast::Pat::PathPat(p) => { | 771 | ast::Pat::PathPat(p) => { |
768 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 772 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
769 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 773 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
770 | } | 774 | } |
771 | ast::Pat::OrPat(p) => { | 775 | ast::Pat::OrPat(p) => { |
@@ -779,7 +783,7 @@ impl ExprCollector<'_> { | |||
779 | } | 783 | } |
780 | ast::Pat::WildcardPat(_) => Pat::Wild, | 784 | ast::Pat::WildcardPat(_) => Pat::Wild, |
781 | ast::Pat::RecordPat(p) => { | 785 | ast::Pat::RecordPat(p) => { |
782 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 786 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
783 | let args: Vec<_> = p | 787 | let args: Vec<_> = p |
784 | .record_pat_field_list() | 788 | .record_pat_field_list() |
785 | .expect("every struct should have a field list") | 789 | .expect("every struct should have a field list") |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 6c7376fad..62a28bdba 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -86,7 +86,7 @@ pub enum Expr { | |||
86 | receiver: ExprId, | 86 | receiver: ExprId, |
87 | method_name: Name, | 87 | method_name: Name, |
88 | args: Vec<ExprId>, | 88 | args: Vec<ExprId>, |
89 | generic_args: Option<GenericArgs>, | 89 | generic_args: Option<Box<GenericArgs>>, |
90 | }, | 90 | }, |
91 | Match { | 91 | Match { |
92 | expr: ExprId, | 92 | expr: ExprId, |
@@ -106,7 +106,7 @@ pub enum Expr { | |||
106 | expr: Option<ExprId>, | 106 | expr: Option<ExprId>, |
107 | }, | 107 | }, |
108 | RecordLit { | 108 | RecordLit { |
109 | path: Option<Path>, | 109 | path: Option<Box<Path>>, |
110 | fields: Vec<RecordLitField>, | 110 | fields: Vec<RecordLitField>, |
111 | spread: Option<ExprId>, | 111 | spread: Option<ExprId>, |
112 | }, | 112 | }, |
@@ -131,7 +131,7 @@ pub enum Expr { | |||
131 | }, | 131 | }, |
132 | Cast { | 132 | Cast { |
133 | expr: ExprId, | 133 | expr: ExprId, |
134 | type_ref: TypeRef, | 134 | type_ref: Box<TypeRef>, |
135 | }, | 135 | }, |
136 | Ref { | 136 | Ref { |
137 | expr: ExprId, | 137 | expr: ExprId, |
@@ -162,7 +162,7 @@ pub enum Expr { | |||
162 | Lambda { | 162 | Lambda { |
163 | args: Vec<PatId>, | 163 | args: Vec<PatId>, |
164 | arg_types: Vec<Option<TypeRef>>, | 164 | arg_types: Vec<Option<TypeRef>>, |
165 | ret_type: Option<TypeRef>, | 165 | ret_type: Option<Box<TypeRef>>, |
166 | body: ExprId, | 166 | body: ExprId, |
167 | }, | 167 | }, |
168 | Tuple { | 168 | Tuple { |
@@ -412,13 +412,13 @@ pub enum Pat { | |||
412 | Wild, | 412 | Wild, |
413 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, | 413 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, |
414 | Or(Vec<PatId>), | 414 | Or(Vec<PatId>), |
415 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, | 415 | Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool }, |
416 | Range { start: ExprId, end: ExprId }, | 416 | Range { start: ExprId, end: ExprId }, |
417 | Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, | 417 | Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, |
418 | Path(Path), | 418 | Path(Box<Path>), |
419 | Lit(ExprId), | 419 | Lit(ExprId), |
420 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, | 420 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
421 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, | 421 | TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> }, |
422 | Ref { pat: PatId, mutability: Mutability }, | 422 | Ref { pat: PatId, mutability: Mutability }, |
423 | Box { inner: PatId }, | 423 | Box { inner: PatId }, |
424 | ConstBlock(ExprId), | 424 | ConstBlock(ExprId), |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index f9c8328f0..b528ff8ba 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -289,6 +289,12 @@ impl From<Name> for Path { | |||
289 | } | 289 | } |
290 | } | 290 | } |
291 | 291 | ||
292 | impl From<Name> for Box<Path> { | ||
293 | fn from(name: Name) -> Box<Path> { | ||
294 | Box::new(Path::from(name)) | ||
295 | } | ||
296 | } | ||
297 | |||
292 | impl From<Name> for ModPath { | 298 | impl From<Name> for ModPath { |
293 | fn from(name: Name) -> ModPath { | 299 | fn from(name: Name) -> ModPath { |
294 | ModPath::from_segments(PathKind::Plain, iter::once(name)) | 300 | ModPath::from_segments(PathKind::Plain, iter::once(name)) |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index dab137ae1..5b3cdab4e 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -318,7 +318,13 @@ impl<'a> InferenceContext<'a> { | |||
318 | self.normalize_associated_types_in(ret_ty) | 318 | self.normalize_associated_types_in(ret_ty) |
319 | } | 319 | } |
320 | Expr::MethodCall { receiver, args, method_name, generic_args } => self | 320 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
321 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), | 321 | .infer_method_call( |
322 | tgt_expr, | ||
323 | *receiver, | ||
324 | &args, | ||
325 | &method_name, | ||
326 | generic_args.as_deref(), | ||
327 | ), | ||
322 | Expr::Match { expr, arms } => { | 328 | Expr::Match { expr, arms } => { |
323 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 329 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
324 | 330 | ||
@@ -399,7 +405,7 @@ impl<'a> InferenceContext<'a> { | |||
399 | TyKind::Never.intern(&Interner) | 405 | TyKind::Never.intern(&Interner) |
400 | } | 406 | } |
401 | Expr::RecordLit { path, fields, spread } => { | 407 | Expr::RecordLit { path, fields, spread } => { |
402 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 408 | let (ty, def_id) = self.resolve_variant(path.as_deref()); |
403 | if let Some(variant) = def_id { | 409 | if let Some(variant) = def_id { |
404 | self.write_variant_resolution(tgt_expr.into(), variant); | 410 | self.write_variant_resolution(tgt_expr.into(), variant); |
405 | } | 411 | } |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index fc2bc3ef8..12431ae07 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -174,7 +174,7 @@ impl<'a> InferenceContext<'a> { | |||
174 | TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner) | 174 | TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner) |
175 | } | 175 | } |
176 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 176 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
177 | p.as_ref(), | 177 | p.as_deref(), |
178 | subpats, | 178 | subpats, |
179 | expected, | 179 | expected, |
180 | default_bm, | 180 | default_bm, |
@@ -182,7 +182,7 @@ impl<'a> InferenceContext<'a> { | |||
182 | *ellipsis, | 182 | *ellipsis, |
183 | ), | 183 | ), |
184 | Pat::Record { path: p, args: fields, ellipsis: _ } => { | 184 | Pat::Record { path: p, args: fields, ellipsis: _ } => { |
185 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) | 185 | self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat) |
186 | } | 186 | } |
187 | Pat::Path(path) => { | 187 | Pat::Path(path) => { |
188 | // FIXME use correct resolver for the surrounding expression | 188 | // FIXME use correct resolver for the surrounding expression |
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml index c318a68f7..894944b18 100644 --- a/crates/vfs/Cargo.toml +++ b/crates/vfs/Cargo.toml | |||
@@ -14,3 +14,4 @@ rustc-hash = "1.0" | |||
14 | fst = "0.4" | 14 | fst = "0.4" |
15 | 15 | ||
16 | paths = { path = "../paths", version = "0.0.0" } | 16 | paths = { path = "../paths", version = "0.0.0" } |
17 | indexmap = "1.6.2" | ||
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs index 2189e5e25..6e049f0d4 100644 --- a/crates/vfs/src/path_interner.rs +++ b/crates/vfs/src/path_interner.rs | |||
@@ -1,15 +1,22 @@ | |||
1 | //! Maps paths to compact integer ids. We don't care about clearings paths which | 1 | //! Maps paths to compact integer ids. We don't care about clearings paths which |
2 | //! no longer exist -- the assumption is total size of paths we ever look at is | 2 | //! no longer exist -- the assumption is total size of paths we ever look at is |
3 | //! not too big. | 3 | //! not too big. |
4 | use rustc_hash::FxHashMap; | 4 | use std::hash::BuildHasherDefault; |
5 | |||
6 | use indexmap::IndexSet; | ||
7 | use rustc_hash::FxHasher; | ||
5 | 8 | ||
6 | use crate::{FileId, VfsPath}; | 9 | use crate::{FileId, VfsPath}; |
7 | 10 | ||
8 | /// Structure to map between [`VfsPath`] and [`FileId`]. | 11 | /// Structure to map between [`VfsPath`] and [`FileId`]. |
9 | #[derive(Default)] | ||
10 | pub(crate) struct PathInterner { | 12 | pub(crate) struct PathInterner { |
11 | map: FxHashMap<VfsPath, FileId>, | 13 | map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>, |
12 | vec: Vec<VfsPath>, | 14 | } |
15 | |||
16 | impl Default for PathInterner { | ||
17 | fn default() -> Self { | ||
18 | Self { map: IndexSet::default() } | ||
19 | } | ||
13 | } | 20 | } |
14 | 21 | ||
15 | impl PathInterner { | 22 | impl PathInterner { |
@@ -17,7 +24,7 @@ impl PathInterner { | |||
17 | /// | 24 | /// |
18 | /// If `path` does not exists in `self`, returns [`None`]. | 25 | /// If `path` does not exists in `self`, returns [`None`]. |
19 | pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { | 26 | pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { |
20 | self.map.get(path).copied() | 27 | self.map.get_index_of(path).map(|i| FileId(i as u32)) |
21 | } | 28 | } |
22 | 29 | ||
23 | /// Insert `path` in `self`. | 30 | /// Insert `path` in `self`. |
@@ -25,13 +32,9 @@ impl PathInterner { | |||
25 | /// - If `path` already exists in `self`, returns its associated id; | 32 | /// - If `path` already exists in `self`, returns its associated id; |
26 | /// - Else, returns a newly allocated id. | 33 | /// - Else, returns a newly allocated id. |
27 | pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { | 34 | pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { |
28 | if let Some(id) = self.get(&path) { | 35 | let (id, _added) = self.map.insert_full(path); |
29 | return id; | 36 | assert!(id < u32::MAX as usize); |
30 | } | 37 | FileId(id as u32) |
31 | let id = FileId(self.vec.len() as u32); | ||
32 | self.map.insert(path.clone(), id); | ||
33 | self.vec.push(path); | ||
34 | id | ||
35 | } | 38 | } |
36 | 39 | ||
37 | /// Returns the path corresponding to `id`. | 40 | /// Returns the path corresponding to `id`. |
@@ -40,6 +43,6 @@ impl PathInterner { | |||
40 | /// | 43 | /// |
41 | /// Panics if `id` does not exists in `self`. | 44 | /// Panics if `id` does not exists in `self`. |
42 | pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { | 45 | pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { |
43 | &self.vec[id.0 as usize] | 46 | self.map.get_index(id.0 as usize).unwrap() |
44 | } | 47 | } |
45 | } | 48 | } |