From 3bdb03f8fd29a17d9b00736c22b25d1a31e00d29 Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Tue, 16 Jan 2024 12:43:36 +1100 Subject: [PATCH 1/6] use rayon for parse_ast_to_typed_tokens function --- sway-lsp/src/core/session.rs | 40 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sway-lsp/src/core/session.rs b/sway-lsp/src/core/session.rs index 7b43706ca0b..07201fa5fab 100644 --- a/sway-lsp/src/core/session.rs +++ b/sway-lsp/src/core/session.rs @@ -24,7 +24,7 @@ use lsp_types::{ }; use parking_lot::RwLock; use pkg::{manifest::ManifestFile, BuildPlan}; -use rayon::iter::{ParallelBridge, ParallelIterator}; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use std::{ ops::Deref, path::PathBuf, @@ -561,16 +561,19 @@ fn parse_ast_to_tokens( ctx: &ParseContext, f: impl Fn(&AstNode, &ParseContext) + Sync, ) { - let root_nodes = parse_program.root.tree.root_nodes.iter(); - let sub_nodes = parse_program + let nodes = parse_program .root - .submodules_recursive() - .flat_map(|(_, submodule)| &submodule.module.tree.root_nodes); - - root_nodes - .chain(sub_nodes) - .par_bridge() - .for_each(|n| f(n, ctx)); + .tree + .root_nodes + .iter() + .chain( + parse_program + .root + .submodules_recursive() + .flat_map(|(_, submodule)| &submodule.module.tree.root_nodes), + ) + .collect::>(); + nodes.par_iter().for_each(|n| f(n, ctx)); } /// Parse the [ty::TyProgram] AST to populate the [TokenMap] with typed AST nodes. @@ -579,13 +582,18 @@ fn parse_ast_to_typed_tokens( ctx: &ParseContext, f: impl Fn(&ty::TyAstNode, &ParseContext) + Sync, ) { - let root_nodes = typed_program.root.all_nodes.iter(); - let sub_nodes = typed_program + let nodes = typed_program .root - .submodules_recursive() - .flat_map(|(_, submodule)| submodule.module.all_nodes.iter()); - - root_nodes.chain(sub_nodes).for_each(|n| f(n, ctx)); + .all_nodes + .iter() + .chain( + typed_program + .root + .submodules_recursive() + .flat_map(|(_, submodule)| submodule.module.all_nodes.iter()), + ) + .collect::>(); + nodes.par_iter().for_each(|n| f(n, ctx)); } #[cfg(test)] From f55b47a7e35cc365276138a2c164cd30beeb82b9 Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Wed, 17 Jan 2024 12:13:02 +1100 Subject: [PATCH 2/6] add try_get_mut_with_retry method to TokenMap --- sway-lsp/src/core/session.rs | 2 +- sway-lsp/src/core/token_map.rs | 34 ++++- sway-lsp/src/traverse/dependency.rs | 2 +- sway-lsp/src/traverse/typed_tree.rs | 186 +++++++++++----------------- 4 files changed, 103 insertions(+), 121 deletions(-) diff --git a/sway-lsp/src/core/session.rs b/sway-lsp/src/core/session.rs index 07201fa5fab..50eadd4f35a 100644 --- a/sway-lsp/src/core/session.rs +++ b/sway-lsp/src/core/session.rs @@ -590,7 +590,7 @@ fn parse_ast_to_typed_tokens( typed_program .root .submodules_recursive() - .flat_map(|(_, submodule)| submodule.module.all_nodes.iter()), + .flat_map(|(_, submodule)| &submodule.module.all_nodes), ) .collect::>(); nodes.par_iter().for_each(|n| f(n, ctx)); diff --git a/sway-lsp/src/core/token_map.rs b/sway-lsp/src/core/token_map.rs index a4bea8b90cf..fae101ec583 100644 --- a/sway-lsp/src/core/token_map.rs +++ b/sway-lsp/src/core/token_map.rs @@ -1,6 +1,10 @@ use crate::core::token::{self, Token, TokenIdent, TypedAstToken}; -use dashmap::DashMap; +use dashmap::{mapref::one::RefMut, try_result::TryResult, DashMap}; use lsp_types::{Position, Url}; +use std::{ + time::Duration, + thread, +}; use sway_core::{language::ty, type_system::TypeId, Engines}; use sway_types::{Ident, SourceEngine, Spanned}; @@ -14,12 +18,38 @@ pub use crate::core::token_map_ext::TokenMapExt; #[derive(Debug, Default)] pub struct TokenMap(DashMap); -impl TokenMap { +impl<'a> TokenMap { /// Create a new token map. pub fn new() -> TokenMap { TokenMap(DashMap::with_capacity(2048)) } + /// Attempts to get a mutable reference to a token with retries on lock. Retries up to 3 times with increasing backoff (1ms, 10ms, 100ms). + pub fn try_get_mut_with_retry( + &'a self, + ident: &TokenIdent, + ) -> Option> { + const MAX_RETRIES: usize = 3; + let backoff_times = [1, 10, 100]; // Backoff times in milliseconds for each retry + for i in 0..MAX_RETRIES { + match self.try_get_mut(ident) { + TryResult::Present(token) => return Some(token), + TryResult::Absent => return None, + TryResult::Locked => { + eprintln!("Failed to get token, retrying attmpt {}: {:#?}", i, ident); + // Wait for the specified backoff time before retrying + let backoff_time = Duration::from_millis(backoff_times[i]); + thread::sleep(backoff_time); + } + } + } + eprintln!( + "UUHHH OOOOOHHH Failed to get token after {} retries: {:#?}", + MAX_RETRIES, ident + ); + None // Return None if all retries are exhausted + } + /// Create a custom iterator for the TokenMap. /// /// The iterator returns ([Ident], [Token]) pairs. diff --git a/sway-lsp/src/traverse/dependency.rs b/sway-lsp/src/traverse/dependency.rs index cde3f2942c6..6be30940306 100644 --- a/sway-lsp/src/traverse/dependency.rs +++ b/sway-lsp/src/traverse/dependency.rs @@ -45,7 +45,7 @@ pub fn collect_typed_declaration(node: &ty::TyAstNode, ctx: &ParseContext) { }; let token_ident = ctx.ident(&ident); - if let Some(mut token) = ctx.tokens.try_get_mut(&token_ident).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&token_ident) { token.typed = Some(typed_token); token.type_def = Some(TypeDefinition::Ident(ident)); } diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index 02a7a18607c..a1460e6a00a 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -49,8 +49,7 @@ impl<'a> TypedTree<'a> { if let Some(mut token) = self .ctx .tokens - .try_get_mut(&self.ctx.ident(&Ident::new(mod_name_span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&self.ctx.ident(&Ident::new(mod_name_span.clone()))) { token.typed = Some(TypedAstToken::TypedModuleName); token.type_def = Some(TypeDefinition::Ident(Ident::new(module.span.clone()))); @@ -107,8 +106,7 @@ impl Parse for ty::TySideEffect { }, ) => { for (mod_path, ident) in iter_prefixes(call_path).zip(call_path) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(TypedAstToken::TypedUseStatement(use_statement.clone())); if let Some(span) = ctx @@ -122,8 +120,7 @@ impl Parse for ty::TySideEffect { } match &import_type { ImportType::Item(item) => { - if let Some(mut token) = - ctx.tokens.try_get_mut(&ctx.ident(item)).try_unwrap() + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(item)) { token.typed = Some(TypedAstToken::TypedUseStatement(use_statement.clone())); @@ -148,7 +145,7 @@ impl Parse for ty::TySideEffect { // the alias should take on the same symbol kind and type definition if let Some(alias) = alias { if let Some(mut token) = - ctx.tokens.try_get_mut(&ctx.ident(alias)).try_unwrap() + ctx.tokens.try_get_mut_with_retry(&ctx.ident(alias)) { token.typed = Some(TypedAstToken::TypedUseStatement( use_statement.clone(), @@ -162,8 +159,7 @@ impl Parse for ty::TySideEffect { ImportType::SelfImport(span) => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(span.clone()))) { token.typed = Some(TypedAstToken::TypedUseStatement(use_statement.clone())); @@ -186,7 +182,7 @@ impl Parse for ty::TySideEffect { visibility: _, }, ) => { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(mod_name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(mod_name)) { token.typed = Some(TypedAstToken::TypedIncludeStatement( include_statement.clone(), )); @@ -209,8 +205,7 @@ impl Parse for ty::TyExpression { ty::TyExpressionVariant::Literal { .. } => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(self.span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(self.span.clone()))) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); } @@ -240,8 +235,7 @@ impl Parse for ty::TyExpression { let prefixes = if let Some(impl_type_name) = implementing_type_name { // the last prefix of the call path is not a module but a type if let Some((last, prefixes)) = call_path.prefixes.split_last() { - if let Some(mut token) = - ctx.tokens.try_get_mut(&ctx.ident(last)).try_unwrap() + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(last)) { if let Some(call_path_typeid) = call_path_typeid { token.typed = Some(TypedAstToken::Ident(impl_type_name.clone())); @@ -258,8 +252,7 @@ impl Parse for ty::TyExpression { collect_call_path_prefixes(ctx, prefixes); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&call_path.suffix)) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); let function_decl = ctx.engines.de().get_function(fn_ref); @@ -267,8 +260,7 @@ impl Parse for ty::TyExpression { } contract_call_params.values().for_each(|exp| exp.parse(ctx)); for (ident, exp) in arguments { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(TypedAstToken::Ident(ident.clone())); } exp.parse(ctx); @@ -306,8 +298,7 @@ impl Parse for ty::TyExpression { } if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(span.clone()))) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); token.type_def = Some(TypeDefinition::Ident(name.clone())); @@ -333,8 +324,7 @@ impl Parse for ty::TyExpression { } => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&call_path_binding.inner.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&call_path_binding.inner.suffix)) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); token.type_def = Some(TypeDefinition::TypeId(self.return_type)); @@ -349,7 +339,7 @@ impl Parse for ty::TyExpression { collect_call_path_prefixes(ctx, &call_path_binding.inner.prefixes); fields.iter().for_each(|field| { if let Some(mut token) = - ctx.tokens.try_get_mut(&ctx.ident(&field.name)).try_unwrap() + ctx.tokens.try_get_mut_with_retry(&ctx.ident(&field.name)) { token.typed = Some(TypedAstToken::TypedExpression(field.value.clone())); @@ -407,11 +397,9 @@ impl Parse for ty::TyExpression { .. } => { prefix.parse(ctx); - if let Some(mut token) = ctx - .tokens - .try_get_mut(&ctx.ident(&Ident::new(field_instantiation_span.clone()))) - .try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry( + &ctx.ident(&Ident::new(field_instantiation_span.clone())), + ) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); token.type_def = Some(TypeDefinition::Ident(field_to_access.name.clone())); } @@ -424,8 +412,7 @@ impl Parse for ty::TyExpression { prefix.parse(ctx); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(elem_to_access_span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(elem_to_access_span.clone()))) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); } @@ -440,8 +427,7 @@ impl Parse for ty::TyExpression { } => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&call_path_binding.inner.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&call_path_binding.inner.suffix)) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); token.type_def = Some(TypeDefinition::Ident(enum_ref.name().clone())); @@ -454,11 +440,9 @@ impl Parse for ty::TyExpression { collect_type_argument(ctx, type_arg); }); collect_call_path_prefixes(ctx, &call_path_binding.inner.prefixes); - if let Some(mut token) = ctx - .tokens - .try_get_mut(&ctx.ident(&Ident::new(variant_instantiation_span.clone()))) - .try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry( + &ctx.ident(&Ident::new(variant_instantiation_span.clone())), + ) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); token.type_def = Some(TypeDefinition::Ident(variant_name.clone())); } @@ -472,8 +456,7 @@ impl Parse for ty::TyExpression { collect_call_path_prefixes(ctx, &abi_name.prefixes); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&abi_name.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&abi_name.suffix)) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); if let Some(abi_def_ident) = ctx @@ -489,13 +472,9 @@ impl Parse for ty::TyExpression { } ty::TyExpressionVariant::StorageAccess(storage_access) => { // collect storage keyword - if let Some(mut token) = ctx - .tokens - .try_get_mut( - &ctx.ident(&Ident::new(storage_access.storage_keyword_span.clone())), - ) - .try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry( + &ctx.ident(&Ident::new(storage_access.storage_keyword_span.clone())), + ) { token.typed = Some(TypedAstToken::TypedStorageAccess(storage_access.clone())); if let Some(storage) = ctx.namespace.get_declared_storage(ctx.engines.de()) { token.type_def = @@ -506,8 +485,7 @@ impl Parse for ty::TyExpression { // collect the first ident as a field of the storage definition if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&head_field.name)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&head_field.name)) { token.typed = Some(TypedAstToken::TypedStorageAccessDescriptor( head_field.clone(), @@ -532,7 +510,7 @@ impl Parse for ty::TyExpression { .zip(storage_access.fields.iter().map(|f| f.type_id)) { if let Some(mut token) = - ctx.tokens.try_get_mut(&ctx.ident(&field.name)).try_unwrap() + ctx.tokens.try_get_mut_with_retry(&ctx.ident(&field.name)) { token.typed = Some(TypedAstToken::Ident(field.name.clone())); match &*ctx.engines.te().get(container_type_id) { @@ -573,10 +551,8 @@ impl Parse for ty::TyExpression { call_path_decl: _, } => { exp.parse(ctx); - if let Some(mut token) = ctx - .tokens - .try_get_mut(&ctx.ident(&variant.name)) - .try_unwrap() + if let Some(mut token) = + ctx.tokens.try_get_mut_with_retry(&ctx.ident(&variant.name)) { token.typed = Some(TypedAstToken::TypedExpression(self.clone())); } @@ -602,7 +578,7 @@ impl Parse for ty::TyExpression { impl Parse for ty::TyVariableDecl { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(TypedAstToken::TypedDeclaration(ty::TyDecl::VariableDecl( Box::new(self.clone()), ))); @@ -635,8 +611,7 @@ impl Parse for ty::FunctionDecl { let typed_token = TypedAstToken::TypedFunctionDeclaration((*func_decl).clone()); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&func_decl.name)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&func_decl.name)) { token.typed = Some(typed_token.clone()); token.type_def = Some(TypeDefinition::Ident(func_decl.name.clone())); @@ -663,7 +638,7 @@ impl Parse for ty::FunctionDecl { trait_constraints.iter().for_each(|constraint| { collect_trait_constraint(ctx, constraint); }); - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(typed_token.clone()); if let Some(param_decl_ident) = func_decl .type_parameters @@ -683,8 +658,7 @@ impl Parse for ty::TraitDecl { let trait_decl = ctx.engines.de().get_trait(&self.decl_id); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&trait_decl.name)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&trait_decl.name)) { token.typed = Some(TypedAstToken::TypedDeclaration(ty::TyDecl::TraitDecl( self.clone(), @@ -719,8 +693,7 @@ impl Parse for ty::StructDecl { let struct_decl = ctx.engines.de().get_struct(&self.decl_id); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&struct_decl.call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&struct_decl.call_path.suffix)) { token.typed = Some(TypedAstToken::TypedDeclaration(ty::TyDecl::StructDecl( self.clone(), @@ -733,8 +706,7 @@ impl Parse for ty::StructDecl { struct_decl.type_parameters.iter().for_each(|type_param| { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&type_param.name_ident)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&type_param.name_ident)) { token.typed = Some(TypedAstToken::TypedParameter(type_param.clone())); token.type_def = Some(TypeDefinition::TypeId(type_param.type_id)); @@ -764,7 +736,7 @@ impl Parse for ty::ImplTrait { ); }); trait_name.prefixes.iter().for_each(|ident| { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(TypedAstToken::Ident(ident.clone())); } }); @@ -777,8 +749,7 @@ impl Parse for ty::ImplTrait { let mut typed_token = None; if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&trait_name.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&trait_name.suffix)) { token.typed = Some(TypedAstToken::TypedDeclaration(ty::TyDecl::ImplTrait( self.clone(), @@ -841,8 +812,7 @@ impl Parse for ty::AbiDecl { let abi_decl = ctx.engines.de().get_abi(&self.decl_id); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&abi_decl.name)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&abi_decl.name)) { token.typed = Some(TypedAstToken::TypedDeclaration(ty::TyDecl::AbiDecl( self.clone(), @@ -874,7 +844,7 @@ impl Parse for ty::AbiDecl { impl Parse for ty::GenericTypeForFunctionScope { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(TypedAstToken::TypedDeclaration( ty::TyDecl::GenericTypeForFunctionScope(self.clone()), )); @@ -887,7 +857,7 @@ impl Parse for ty::StorageDecl { fn parse(&self, ctx: &ParseContext) { let storage_decl = ctx.engines.de().get_storage(&self.decl_id); for field in &storage_decl.fields { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&field.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&field.name)) { token.typed = Some(TypedAstToken::TypedStorageField(field.clone())); token.type_def = Some(TypeDefinition::Ident(field.name.clone())); } @@ -907,7 +877,7 @@ impl Parse for ty::TypeAliasDecl { impl Parse for ty::TyFunctionParameter { fn parse(&self, ctx: &ParseContext) { let typed_token = TypedAstToken::TypedFunctionParameter(self.clone()); - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(typed_token); token.type_def = Some(TypeDefinition::Ident(self.name.clone())); } @@ -917,17 +887,13 @@ impl Parse for ty::TyFunctionParameter { impl Parse for ty::TyTraitFn { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(TypedAstToken::TypedTraitFn(self.clone())); token.type_def = Some(TypeDefinition::Ident(self.name.clone())); } self.parameters.iter().for_each(|param| param.parse(ctx)); let return_ident = Ident::new(self.return_type.span.clone()); - if let Some(mut token) = ctx - .tokens - .try_get_mut(&ctx.ident(&return_ident)) - .try_unwrap() - { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&return_ident)) { token.typed = Some(TypedAstToken::TypedTraitFn(self.clone())); token.type_def = Some(TypeDefinition::TypeId(self.return_type.type_id)); } @@ -936,7 +902,7 @@ impl Parse for ty::TyTraitFn { impl Parse for ty::TyStructField { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(TypedAstToken::TypedStructField(self.clone())); token.type_def = Some(TypeDefinition::Ident(self.name.clone())); } @@ -947,7 +913,7 @@ impl Parse for ty::TyStructField { impl Parse for ty::TyEnumVariant { fn parse(&self, ctx: &ParseContext) { let typed_token = TypedAstToken::TypedEnumVariant(self.clone()); - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(typed_token); token.type_def = Some(TypeDefinition::TypeId(self.type_argument.type_id)); } @@ -958,7 +924,7 @@ impl Parse for ty::TyEnumVariant { impl Parse for ty::TyFunctionDecl { fn parse(&self, ctx: &ParseContext) { let typed_token = TypedAstToken::TypedFunctionDeclaration(self.clone()); - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(typed_token.clone()); token.type_def = Some(TypeDefinition::Ident(self.name.clone())); } @@ -977,7 +943,7 @@ impl Parse for ty::TyFunctionDecl { trait_constraints.iter().for_each(|constraint| { collect_trait_constraint(ctx, constraint); }); - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(typed_token.clone()); if let Some(param_decl_ident) = self .type_parameters @@ -994,7 +960,7 @@ impl Parse for ty::TyFunctionDecl { impl Parse for ty::TyTypeAliasDecl { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.name)) { token.typed = Some(TypedAstToken::TypedTypeAliasDeclaration(self.clone())); token.type_def = Some(TypeDefinition::Ident(self.name.clone())); } @@ -1019,7 +985,7 @@ impl Parse for ty::TyScrutinee { match &self.variant { CatchAll => {} Constant(name, _, const_decl) => { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(name)) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); token.type_def = Some(TypeDefinition::Ident(const_decl.call_path.suffix.clone())); @@ -1028,14 +994,13 @@ impl Parse for ty::TyScrutinee { Literal(_) => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(self.span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(self.span.clone()))) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); } } Variable(ident) => { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); } } @@ -1046,8 +1011,7 @@ impl Parse for ty::TyScrutinee { } => { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&instantiation_call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&instantiation_call_path.suffix)) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); token.type_def = Some(TypeDefinition::Ident(struct_ref.name().clone())); @@ -1065,7 +1029,7 @@ impl Parse for ty::TyScrutinee { instantiation_call_path.prefixes.split_last() { // the last prefix of the call path is not a module but a type - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(last)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(last)) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); token.type_def = Some(TypeDefinition::Ident(enum_ref.name().clone())); } @@ -1076,8 +1040,7 @@ impl Parse for ty::TyScrutinee { collect_call_path_prefixes(ctx, prefixes); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&instantiation_call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&instantiation_call_path.suffix)) { token.typed = Some(TypedAstToken::TypedScrutinee(self.clone())); token.type_def = Some(TypeDefinition::Ident(variant.name.clone())); @@ -1093,7 +1056,7 @@ impl Parse for ty::TyScrutinee { impl Parse for ty::TyStructScrutineeField { fn parse(&self, ctx: &ParseContext) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(&self.field)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&self.field)) { token.typed = Some(TypedAstToken::TyStructScrutineeField(self.clone())); token.type_def = Some(TypeDefinition::Ident(self.field_def_name.clone())); } @@ -1108,14 +1071,13 @@ impl Parse for ty::TyReassignment { self.rhs.parse(ctx); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&self.lhs_base_name)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&self.lhs_base_name)) { token.typed = Some(TypedAstToken::TypedReassignment(self.clone())); } self.lhs_indices.iter().for_each(|proj_kind| { if let ty::ProjectionKind::StructField { name } = proj_kind { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(name)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(name)) { token.typed = Some(TypedAstToken::TypedReassignment(self.clone())); if let Some(struct_decl) = &ctx .tokens @@ -1187,8 +1149,7 @@ fn collect_call_path_tree(ctx: &ParseContext, tree: &CallPathTree, type_arg: &Ty collect_call_path_prefixes(ctx, &abi_call_path.call_path.prefixes); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&abi_call_path.call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&abi_call_path.call_path.suffix)) { token.typed = Some(TypedAstToken::TypedArgument(type_arg.clone())); if let Some(abi_def_ident) = ctx @@ -1208,7 +1169,7 @@ fn collect_call_path_tree(ctx: &ParseContext, tree: &CallPathTree, type_arg: &Ty fn collect_call_path_prefixes(ctx: &ParseContext, prefixes: &[Ident]) { for (mod_path, ident) in iter_prefixes(prefixes).zip(prefixes) { - if let Some(mut token) = ctx.tokens.try_get_mut(&ctx.ident(ident)).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.typed = Some(TypedAstToken::Ident(ident.clone())); if let Some(span) = ctx .namespace @@ -1225,7 +1186,7 @@ fn collect_call_path_prefixes(ctx: &ParseContext, prefixes: &[Ident]) { fn collect_const_decl(ctx: &ParseContext, const_decl: &ty::TyConstantDecl, ident: Option<&Ident>) { let key = ctx.ident(ident.unwrap_or(const_decl.name())); - if let Some(mut token) = ctx.tokens.try_get_mut(&key).try_unwrap() { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&key) { token.typed = Some(TypedAstToken::TypedConstantDeclaration(const_decl.clone())); token.type_def = Some(TypeDefinition::Ident(const_decl.call_path.suffix.clone())); } @@ -1240,8 +1201,7 @@ fn collect_const_decl(ctx: &ParseContext, const_decl: &ty::TyConstantDecl, ident fn collect_trait_type_decl(ctx: &ParseContext, type_decl: &ty::TyTraitType, span: &Span) { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(span.clone()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(span.clone()))) { token.typed = Some(TypedAstToken::TypedTraitTypeDeclaration(type_decl.clone())); token.type_def = Some(TypeDefinition::Ident(type_decl.name.clone())); @@ -1272,8 +1232,7 @@ fn collect_type_id( let decl = ctx.engines.de().get_enum(decl_ref); if let Some(token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(type_span))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(type_span))) { assign_type_to_token(token, symbol_kind, typed_token.clone(), type_id); } @@ -1293,8 +1252,7 @@ fn collect_type_id( let decl = ctx.engines.de().get_struct(decl_ref); if let Some(token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(type_span))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(type_span))) { assign_type_to_token(token, symbol_kind, typed_token.clone(), type_id); } @@ -1318,8 +1276,7 @@ fn collect_type_id( collect_qualified_path_root(ctx, name.qualified_path_root.clone()); if let Some(token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(name.call_path.span()))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(name.call_path.span()))) { assign_type_to_token(token, symbol_kind, typed_token.clone(), type_id); } @@ -1337,8 +1294,7 @@ fn collect_type_id( _ => { if let Some(token) = ctx .tokens - .try_get_mut(&ctx.ident(&Ident::new(type_span))) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&Ident::new(type_span))) { assign_type_to_token(token, symbol_kind, typed_token.clone(), type_id); } @@ -1369,8 +1325,7 @@ fn collect_trait_constraint( collect_call_path_prefixes(ctx, &trait_name.prefixes); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&trait_name.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&trait_name.suffix)) { token.typed = Some(TypedAstToken::TypedTraitConstraint( trait_constraint.clone(), @@ -1392,8 +1347,7 @@ fn collect_trait_constraint( fn collect_supertrait(ctx: &ParseContext, supertrait: &Supertrait) { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&supertrait.name.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&supertrait.name.suffix)) { token.typed = Some(TypedAstToken::TypedSupertrait(supertrait.clone())); token.type_def = if let Some(decl_ref) = &supertrait.decl_ref { @@ -1409,8 +1363,7 @@ fn collect_enum(ctx: &ParseContext, decl_id: &DeclId, declaratio let enum_decl = ctx.engines.de().get_enum(decl_id); if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&enum_decl.call_path.suffix)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&enum_decl.call_path.suffix)) { token.typed = Some(TypedAstToken::TypedDeclaration(declaration.clone())); token.type_def = Some(TypeDefinition::Ident(enum_decl.call_path.suffix.clone())); @@ -1418,8 +1371,7 @@ fn collect_enum(ctx: &ParseContext, decl_id: &DeclId, declaratio enum_decl.type_parameters.iter().for_each(|type_param| { if let Some(mut token) = ctx .tokens - .try_get_mut(&ctx.ident(&type_param.name_ident)) - .try_unwrap() + .try_get_mut_with_retry(&ctx.ident(&type_param.name_ident)) { token.typed = Some(TypedAstToken::TypedParameter(type_param.clone())); token.type_def = Some(TypeDefinition::TypeId(type_param.type_id)); From 878968026483f3b9fc05556a45b896b8d2f5c40e Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Wed, 17 Jan 2024 12:17:56 +1100 Subject: [PATCH 3/6] clippy --- sway-lsp/src/core/token_map.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sway-lsp/src/core/token_map.rs b/sway-lsp/src/core/token_map.rs index fae101ec583..a13f90f7a18 100644 --- a/sway-lsp/src/core/token_map.rs +++ b/sway-lsp/src/core/token_map.rs @@ -1,10 +1,7 @@ use crate::core::token::{self, Token, TokenIdent, TypedAstToken}; use dashmap::{mapref::one::RefMut, try_result::TryResult, DashMap}; use lsp_types::{Position, Url}; -use std::{ - time::Duration, - thread, -}; +use std::{thread, time::Duration}; use sway_core::{language::ty, type_system::TypeId, Engines}; use sway_types::{Ident, SourceEngine, Spanned}; @@ -24,21 +21,22 @@ impl<'a> TokenMap { TokenMap(DashMap::with_capacity(2048)) } - /// Attempts to get a mutable reference to a token with retries on lock. Retries up to 3 times with increasing backoff (1ms, 10ms, 100ms). + /// Attempts to get a mutable reference to a token with retries on lock. + /// Retries up to 3 times with increasing backoff (1ms, 10ms, 100ms). pub fn try_get_mut_with_retry( &'a self, ident: &TokenIdent, ) -> Option> { const MAX_RETRIES: usize = 3; let backoff_times = [1, 10, 100]; // Backoff times in milliseconds for each retry - for i in 0..MAX_RETRIES { + for (i, sleep) in backoff_times.iter().enumerate().take(MAX_RETRIES) { match self.try_get_mut(ident) { TryResult::Present(token) => return Some(token), TryResult::Absent => return None, TryResult::Locked => { eprintln!("Failed to get token, retrying attmpt {}: {:#?}", i, ident); // Wait for the specified backoff time before retrying - let backoff_time = Duration::from_millis(backoff_times[i]); + let backoff_time = Duration::from_millis(*sleep); thread::sleep(backoff_time); } } From 219a3619830e51dc876fcff69547567c16e9b316 Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Wed, 17 Jan 2024 14:40:39 +1100 Subject: [PATCH 4/6] reduce backoff time to microseconds --- sway-lsp/src/core/token_map.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sway-lsp/src/core/token_map.rs b/sway-lsp/src/core/token_map.rs index a13f90f7a18..85340904e30 100644 --- a/sway-lsp/src/core/token_map.rs +++ b/sway-lsp/src/core/token_map.rs @@ -22,28 +22,33 @@ impl<'a> TokenMap { } /// Attempts to get a mutable reference to a token with retries on lock. - /// Retries up to 3 times with increasing backoff (1ms, 10ms, 100ms). + /// Retries up to 7 times with increasing backoff (1us, 10us, 100us, 500us, 1ms, 10ms, 100ms). pub fn try_get_mut_with_retry( &'a self, ident: &TokenIdent, ) -> Option> { - const MAX_RETRIES: usize = 3; - let backoff_times = [1, 10, 100]; // Backoff times in milliseconds for each retry + const MAX_RETRIES: usize = 7; + let backoff_times = [1, 10, 100, 500, 1_000, 10_000, 100_000]; // Backoff times in microseconds for (i, sleep) in backoff_times.iter().enumerate().take(MAX_RETRIES) { match self.try_get_mut(ident) { TryResult::Present(token) => return Some(token), TryResult::Absent => return None, TryResult::Locked => { - eprintln!("Failed to get token, retrying attmpt {}: {:#?}", i, ident); + tracing::warn!( + "Failed to get token, retrying attmpt {}: {:#?}", + i, + ident.name + ); // Wait for the specified backoff time before retrying - let backoff_time = Duration::from_millis(*sleep); + let backoff_time = Duration::from_micros(*sleep); thread::sleep(backoff_time); } } } - eprintln!( - "UUHHH OOOOOHHH Failed to get token after {} retries: {:#?}", - MAX_RETRIES, ident + tracing::error!( + "Failed to get token after {} retries: {:#?}", + MAX_RETRIES, + ident ); None // Return None if all retries are exhausted } From 8be57096f5634652cb6ab05c0287709b0f4cfe1a Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Wed, 17 Jan 2024 14:53:31 +1100 Subject: [PATCH 5/6] try in nanoseconds --- sway-lsp/src/core/token_map.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway-lsp/src/core/token_map.rs b/sway-lsp/src/core/token_map.rs index 85340904e30..4ade6dcdd77 100644 --- a/sway-lsp/src/core/token_map.rs +++ b/sway-lsp/src/core/token_map.rs @@ -22,13 +22,13 @@ impl<'a> TokenMap { } /// Attempts to get a mutable reference to a token with retries on lock. - /// Retries up to 7 times with increasing backoff (1us, 10us, 100us, 500us, 1ms, 10ms, 100ms). + /// Retries up to 8 times with increasing backoff (1ns, 10ns, 100ns, 500ns, 1µs, 10µs, 100µs, 1ms). pub fn try_get_mut_with_retry( &'a self, ident: &TokenIdent, ) -> Option> { - const MAX_RETRIES: usize = 7; - let backoff_times = [1, 10, 100, 500, 1_000, 10_000, 100_000]; // Backoff times in microseconds + const MAX_RETRIES: usize = 8; + let backoff_times = [1, 10, 100, 500, 1_000, 10_000, 100_000, 1_000_000]; // Backoff times in nanoseconds for (i, sleep) in backoff_times.iter().enumerate().take(MAX_RETRIES) { match self.try_get_mut(ident) { TryResult::Present(token) => return Some(token), @@ -40,7 +40,7 @@ impl<'a> TokenMap { ident.name ); // Wait for the specified backoff time before retrying - let backoff_time = Duration::from_micros(*sleep); + let backoff_time = Duration::from_nanos(*sleep); thread::sleep(backoff_time); } } From 67f3c6e23fc96765dae3a65b3143c70ef4f21f1b Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Wed, 17 Jan 2024 16:33:13 +1100 Subject: [PATCH 6/6] add 2 longer conservative durations --- sway-lsp/src/core/token_map.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sway-lsp/src/core/token_map.rs b/sway-lsp/src/core/token_map.rs index 4ade6dcdd77..3031f87c5cc 100644 --- a/sway-lsp/src/core/token_map.rs +++ b/sway-lsp/src/core/token_map.rs @@ -22,13 +22,15 @@ impl<'a> TokenMap { } /// Attempts to get a mutable reference to a token with retries on lock. - /// Retries up to 8 times with increasing backoff (1ns, 10ns, 100ns, 500ns, 1µs, 10µs, 100µs, 1ms). + /// Retries up to 10 times with increasing backoff (1ns, 10ns, 100ns, 500ns, 1µs, 10µs, 100µs, 1ms, 10ms, 50ms). pub fn try_get_mut_with_retry( &'a self, ident: &TokenIdent, ) -> Option> { - const MAX_RETRIES: usize = 8; - let backoff_times = [1, 10, 100, 500, 1_000, 10_000, 100_000, 1_000_000]; // Backoff times in nanoseconds + const MAX_RETRIES: usize = 10; + let backoff_times = [ + 1, 10, 100, 500, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 50_000_000, + ]; // Backoff times in nanoseconds for (i, sleep) in backoff_times.iter().enumerate().take(MAX_RETRIES) { match self.try_get_mut(ident) { TryResult::Present(token) => return Some(token),