mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
perf(lsp): cache completion item resolution during request (#27831)
This commit adds a simple HashMap cache to completion requests. On a test project the time to compute completions went from 1200ms to 75ms and the cache contained ~300 entries when 8000 completion items were produced by the TSC. This is a short-lived cache and is discarded once the completion request is finished. In a follow up commits we could make it persist between requests.
This commit is contained in:
parent
77f6bd0db3
commit
244bf5c2be
1 changed files with 18 additions and 3 deletions
|
@ -3683,6 +3683,10 @@ impl CompletionInfo {
|
||||||
position: u32,
|
position: u32,
|
||||||
language_server: &language_server::Inner,
|
language_server: &language_server::Inner,
|
||||||
) -> lsp::CompletionResponse {
|
) -> lsp::CompletionResponse {
|
||||||
|
// A cache for costly resolution computations.
|
||||||
|
// On a test project, it was found to speed up completion requests
|
||||||
|
// by 10-20x and contained ~300 entries for 8000 completion items.
|
||||||
|
let mut cache = HashMap::with_capacity(512);
|
||||||
let items = self
|
let items = self
|
||||||
.entries
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -3694,6 +3698,7 @@ impl CompletionInfo {
|
||||||
specifier,
|
specifier,
|
||||||
position,
|
position,
|
||||||
language_server,
|
language_server,
|
||||||
|
&mut cache,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -3898,6 +3903,7 @@ impl CompletionEntry {
|
||||||
self.insert_text.clone()
|
self.insert_text.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn as_completion_item(
|
pub fn as_completion_item(
|
||||||
&self,
|
&self,
|
||||||
line_index: Arc<LineIndex>,
|
line_index: Arc<LineIndex>,
|
||||||
|
@ -3906,6 +3912,7 @@ impl CompletionEntry {
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
position: u32,
|
position: u32,
|
||||||
language_server: &language_server::Inner,
|
language_server: &language_server::Inner,
|
||||||
|
resolution_cache: &mut HashMap<(ModuleSpecifier, ModuleSpecifier), String>,
|
||||||
) -> Option<lsp::CompletionItem> {
|
) -> Option<lsp::CompletionItem> {
|
||||||
let mut label = self.name.clone();
|
let mut label = self.name.clone();
|
||||||
let mut label_details: Option<lsp::CompletionItemLabelDetails> = None;
|
let mut label_details: Option<lsp::CompletionItemLabelDetails> = None;
|
||||||
|
@ -3964,14 +3971,18 @@ impl CompletionEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(source) = &self.source {
|
if let Some(source) = &self.source {
|
||||||
let mut display_source = source.clone();
|
let mut display_source = source.clone();
|
||||||
if let Some(import_data) = &self.auto_import_data {
|
if let Some(import_data) = &self.auto_import_data {
|
||||||
let import_mapper =
|
let import_mapper =
|
||||||
language_server.get_ts_response_import_mapper(specifier);
|
language_server.get_ts_response_import_mapper(specifier);
|
||||||
if let Some(mut new_specifier) = import_mapper
|
let maybe_cached = resolution_cache
|
||||||
.check_specifier(&import_data.normalized, specifier)
|
.get(&(import_data.normalized.clone(), specifier.clone()))
|
||||||
|
.cloned();
|
||||||
|
if let Some(mut new_specifier) = maybe_cached
|
||||||
|
.or_else(|| {
|
||||||
|
import_mapper.check_specifier(&import_data.normalized, specifier)
|
||||||
|
})
|
||||||
.or_else(|| relative_specifier(specifier, &import_data.normalized))
|
.or_else(|| relative_specifier(specifier, &import_data.normalized))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
ModuleSpecifier::parse(&import_data.raw.module_specifier)
|
ModuleSpecifier::parse(&import_data.raw.module_specifier)
|
||||||
|
@ -3979,6 +3990,10 @@ impl CompletionEntry {
|
||||||
.then(|| import_data.normalized.to_string())
|
.then(|| import_data.normalized.to_string())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
resolution_cache.insert(
|
||||||
|
(import_data.normalized.clone(), specifier.clone()),
|
||||||
|
new_specifier.clone(),
|
||||||
|
);
|
||||||
if new_specifier.contains("/node_modules/") {
|
if new_specifier.contains("/node_modules/") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue